Skip to content

Ignore invalid instruction after jump/call for triggering guided analysis #7999

Description

@fuzyll

What is the feature you'd like to have?
See title.

Is your feature request related to a problem?
When we encounter invalid instructions in a function, we enter Guided Analysis Mode (https://docs.binary.ninja/guide/guided_analysis.html). This helps both us and users in cases where there are things like obfuscated functions that will send analysis going off in directions it shouldn't.

Unfortunately, there's a common pattern used by some compilers for noreturn functions that also currently triggers it. It looks something like this, for RISC-V:

0009b7c4 e0 efe27175 jal t0, sub_ba71a
0009b7c8 e0 ef909158 jal ra, sub_b5550
0009b7cc e0 0000 ??
0009b7ce e0 c175 lui a1, -0x10000 {0xffff0000}
0009b7d0 e0 2246 lw a2, 0x8(sp) {var_d8}
0009b7d2 e0 f18d and a1, a1, a2

The 0000 "instruction" here is intended to trap in the event that something goes wrong and execution comes back from sub_b5550 (which it should not).

We should not enter guided analysis mode in these situations as it prevents analysis in a situation where it should continue.

Are any alternative solutions acceptable?
For the RISC-V case above, I've opened a PR (#7998) to address this by lifting 0000 as a trap instead. But, we should solve this more generally so that other architectures (and, particularly ones that might not be our official ones, but user plugins) are not also running into this.

Activity

  1. plafosse commented on Mar 9, 2026

    @plafosse
    Member

    So are you asking for "heuristic no-return analysis" This is something I've wanted for awhile and something Ghidra already supports.

  2. added
    Component: CoreIssue needs changes to the core
    Core: LLILIssue involves Low Level IL
    Effort: LowIssues require < 1 week of work
    Impact: MediumIssue is impactful with a bad, or no, workaround
    on Mar 9, 2026
  3. rssor commented on Apr 9, 2026

    @rssor
    Member

    Partially? This is also a pretty large regression because now any compiler emitting such guards after noreturn function calls always trips guided analysis mode, meaning the rest of the basic blocks in the function won't be automatically discovered.

  4. bpotchik commented on Apr 10, 2026

    @bpotchik
    Member

    The guided analysis mode should be self-correcting in the presence of incremental analysis in conjunction with no-returns being identified. There could be an new edge case that popped up, or a regression that happened. Is the binary available for this?

  5. plafosse commented on Apr 10, 2026

    @plafosse
    Member

    I think this is the case when no-returns are not automatically identified

  6. fuzyll commented on Apr 10, 2026

    @fuzyll
    ContributorAuthor

    Correct. We are not identifying a no return in this case, causing guided analysis mode to start because we hit an invalid instruction. There is no binary and the issue is trivially reproduced with the information above.

    PR #7998 addresses this specific issue, but by modifying the way we lift the byte sequence 0000 in RISC-V. Alternatives that would fix this case more generally are welcome and preferred, but this issue is bad enough for affected users that I had hoped we could band-aid it for the 5.3 release. The only current solution is that those users need to turn off guided analysis mode entirely to deal with the regression.

  7. zznop commented on Apr 10, 2026

    @zznop
    Member

    I was looking at a binary a while back with this pattern and found that these functions that dropped into guided analysis mode were useful because I was able to identify these patterns more easily and make the callees no-return manually before then disabling guided analysis. Isn't this the kind of scenario that guided analysis was meant for?

  8. bpotchik commented on Apr 10, 2026

    @bpotchik
    Member

    Yeah this is exactly the purpose. Identify and stop analysis before it goes off in the weeds. That pause gives a user the ability to inspect and handle it appropriately.

  9. fuzyll commented on Apr 10, 2026

    @fuzyll
    ContributorAuthor

    If it were difficult to understand that these functions can't return for some reason, yes, guided analysis would probably be beneficial. It'd prevent a bunch of runaway analysis creating incorrect functions and wasting a whole bunch of time.

    But, in this case (the RISC-V example above), it's a straightforward output from the compiler. There is zero reason we shouldn't be handling this automatically, and the degree to which this comes up on certain firmwares for very little benefit turns reversing into a whole lot of manual work.

  10. bpotchik commented on Apr 10, 2026

    @bpotchik
    Member

    I think one observation here is that we could potentially improve the no-return analysis.

  11. zznop commented on Apr 10, 2026

    @zznop
    Member

    We can't handle this in basic block analysis if Binja fails to recognize that a callee is no-return. I like your change to go ahead and lift 0000 as a trap for now. But maybe we need a module-level workflow that looks for jal instructions followed by a 0000 and assign no-return to the callee.

  12. zznop commented on Apr 10, 2026

    @zznop
    Member

    Or yeah, what Brian said about improving no-return analysis for this case.

  13. fuzyll commented on May 25, 2026

    @fuzyll
    ContributorAuthor

    The RISC-V case should be worked around in builds >= 5.4.9470-dev. Leaving the issue open because we still need a more general solution. Whether that's improving the noreturn analysis, changing something about how we lift more generally, modifying guided analysis mode, or something else entirely, I don't know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Component: CoreIssue needs changes to the coreCore: LLILIssue involves Low Level ILEffort: LowIssues require < 1 week of workImpact: MediumIssue is impactful with a bad, or no, workaround

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions