Skip to content

defaultarch: handle caller-set return addresses when inlining calls#8246

Open
appleflyerv3 wants to merge 1 commit into
Vector35:devfrom
appleflyerv3:dev
Open

defaultarch: handle caller-set return addresses when inlining calls#8246
appleflyerv3 wants to merge 1 commit into
Vector35:devfrom
appleflyerv3:dev

Conversation

@appleflyerv3

Copy link
Copy Markdown

detect registers that are set to the caller's next addr before a call is inlined, and therefore treat the jumps to those regs in the callee IL as returns to the call label.

detect registers that are set to the caller's next addr before a call is inlined, and therefore treat the jumps to those regs in the callee IL as returns to the call label.
@CLAassistant

CLAassistant commented Jun 5, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@appleflyerv3

appleflyerv3 commented Jun 5, 2026

Copy link
Copy Markdown
Author

This fix allows Binary Ninja to recognize during function inlining when an inlined function returns by jumping to a register that was set to the caller’s fallthrough address. (lifted via LLIL_JUMP)

For example, this is used by RISC-V LLVM outlined functions such as jal t0, OUTLINED_FUNCTION_*, followed by jr t0 within OUTLINED_FUNCTION_*, where jr t0 is lifted as LLIL_JUMP(t0).
For binaries using this pattern, this allows OUTLINED_FUNCTION_* helpers, which are typically used as stack prologue/epilogue helpers, to be inlined correctly so the caller’s stack state is recovered.

Example:

sub_function:
    jal t0, OUTLINED_FUNCTION_1
    ...
    jal t0, OUTLINED_FUNCTION_2

OUTLINED_FUNCTION_1:
    addi sp, sp, -0x10
    sw   ra, 0xc(sp)
    sw   s0, 0x8(sp)
    sw   s1, 0x4(sp)
    sw   s2, 0x0(sp)
    jr   t0

OUTLINED_FUNCTION_2:
    lw   ra, 0xc(sp)
    lw   s0, 0x8(sp)
    lw   s1, 0x4(sp)
    lw   s2, 0x0(sp)
    addi sp, sp, 0x10
    jr   t0

@zznop

zznop commented Jun 23, 2026

Copy link
Copy Markdown
Member

I have reviewed/tested this PR and added the following commits to the test_pr_8246 branch:

  • This commit avoids treating LLIL_JUMP(reg) as an inline return when the inlined calllee clobbers that register before returning and also adds support for the tailcalls
  • This commit fixes lifting of the RISC-V jal instruction to set the return register when jal is using something other than ra (the link register).

Comment thread defaultarch.cpp
}


static bool IsConstantPointer(LowLevelILInstruction expr, uint64_t value)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this is a misnomer

@appleflyerv3 appleflyerv3 Jun 23, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

the function name?
what would be a more suitable name for this, then?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

IsConstantValue perhaps

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I changed the function name to ConstantCompare since it's not only checking that the expression is a constant, it's also checking if it is equal to value

10e6eb0

@zznop zznop self-assigned this Jun 24, 2026
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.

4 participants