Vector35 / Vector35/binaryninja-api

Reshuffling of custom argument registers ignored

Open
#4,643 0 comments 0 reactions 1 assignee View on GitHub

@D0ntPanic is already working on this.

Since Oct 3, 2023.

Component: Platform Core: Calling Convention Effort: Medium Impact: Medium
Dominant language
C++
Stars
1.3k
Forks
298
Avg merge
5d 5h
Merged PRs (30d)
19

Description

Version and Platform (required):

  • Binary Ninja Version: 3.6.4548-dev Personal (72b6028d)
  • OS: macOS
  • OS Version: 14.0 (23A339)
  • CPU Architecture: Apple silicon

Bug Description:
If I reorder the arguments of a function such that it gets its arguments from other "parameter" registers (seemingly, the ones that are typically used for arguments), then it does not actually show up as a change in signature for the function and things that call it don't show the parameters passed correctly.

Steps To Reproduce:
Please provide all steps required to reproduce the behavior:

  1. Compile the following code:
_foo:
	bl _bar
	add x0, x0, x1
	ret

_bar:
	add x0, x2, x3
	ret
  1. Load into Binary Ninja. Set the type for _bar to be int64_t _bar(int64_t @ x2, int64_t @ x3) (e.g. two non-standard parameters coming from specific registers).
  2. Set the type for _foo to be int64_t _foo(int64_t, int64_t, int64_t, int64_t) (standard AAPCS calling convention with four parameters, first ends up unused).

Expected Behavior:
I expect the signatures to be displayed as I specified. _foo does but _bar shows int64_t _bar(int64_t arg1, int64_t arg2) without the register assignments. I expect the following decompilation for _foo:

int64_t _foo(int64_t arg1, int64_t arg2, int64_t arg3, int64_t arg4)
{
      return (_bar(arg3, arg4) + arg3);
}

Instead I get:

int64_t _foo(int64_t arg1, int64_t arg2, int64_t arg3, int64_t arg4)
{
      return (_bar(arg1, arg2) + arg2);
}

This suggests that the register assignments for _bar have not been done correctly, since it thinks that _bar takes parameters using AAPCS and not the convention I specified.

Screenshots:
image

Additional Information:
The actual reason I want this is for Objective-C retain/release stubs which take parameters in-nonstandard registers. This is my script:

for function in filter(lambda f: f.name.startswith("_objc_retain_"), bv.functions):
	register = function.name.removeprefix("_objc_retain_")
	function.type = f"id {function.name}(id @ {register})"

for function in filter(lambda f: f.name.startswith("_objc_release_"), bv.functions):
	register = function.name.removeprefix("_objc_release_")
	function.type = f"void {function.name}(id @ {register})"

This works for registers like x20 but not x1.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.