Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integer constant args to (some?) arm64 intrinsics turn into booleans in MLIL #6281

Open
droe opened this issue Dec 27, 2024 · 2 comments
Open
Assignees
Labels
Arch: ARM64 Issues with the AArch64 architecture plugin Effort: Trivial Issue should take < 1 day Impact: Medium Issue is impactful with a bad, or no, workaround Lifting issues related to LLIL lifting Type: Bug Issue is a non-crashing bug with repro steps

Comments

@droe
Copy link

droe commented Dec 27, 2024

Version and Platform (required):

  • Binary Ninja Version: 4.3.6613-dev Personal (8d9fa2fc)
  • OS: macOS
  • OS Version: 14.7.2
  • CPU Architecture: arm64

Bug Description:
Immediate arguments to Arm Neon intrinsics such as vcvtd_n_s64_f64 (for fcvtzs) are turned from integer constants in LLIL to booleans in MLIL. Semantics of the n argument is the bit position of the fixed point, not a boolean, so the integer constant should be preserved with its value, not converted to a boolean.

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

  1. Create a file containing the four bytes bb fc 51 5f, e.g. using echo -n 'BB FC 51 5F'|xxd -p -r> test.bin
  2. Load test.bin into Binja, choosing AArch64 as architecture
  3. Create procedure at offset 0 by pressing P
  4. Notice how in Low Level IL, the instruction is d27 = vcvtd_n_s64_f64(d5, 0x2f)
  5. Notice how in Medium Level IL, the instruction is temp0 = vcvtd_n_s64_f64(arg6, true)

In MLIL, querying the instruction in the console gives:

>>> current_il_instruction
<MediumLevelILIntrinsic: temp0 = vcvtd_n_s64_f64(arg6, true)>
>>> current_il_instruction.operands
[[<var uint64_t temp0>], <ILIntrinsic: vcvtd_n_s64_f64 - aarch64>, [<MediumLevelILVar: arg6>, <MediumLevelILConst: true>]]
>>> current_il_instruction.operands[2][1]
<MediumLevelILConst: true>
>>> current_il_instruction.operands[2][1].value
<const 0x1>

Expected Behavior:
MLIL, HLIL, pseudo c etc to show the second argument to the intrinsic as 0x2f, not true or 0x1.

Binary:
echo -n 'BB FC 51 5F'|xxd -p -r> test.bin

Also reproduces for me with proper binaries containing similar Arm Neon intrinsics for other fcvtzs variants.

Additional Information:
Not sure where Binja takes the type signatures for intrinsics from; I was wondering if it's just missing the prototype for some of the intrinsics. But even with an unknown prototype I would expect it to not convert constant integers to booleans, unless an intrinsic explicitly had a parameter with boolean semantics.

@xusheng6 xusheng6 added Type: Bug Issue is a non-crashing bug with repro steps Component: Core Issue needs changes to the core Core: MLIL Issue involves Medium Level IL Effort: Medium Issue should take < 1 month Impact: Medium Issue is impactful with a bad, or no, workaround labels Jan 6, 2025
@plafosse plafosse added Arch: ARM64 Issues with the AArch64 architecture plugin State: Awaiting Triage Issue is waiting for more in-depth triage from a developer labels Jan 14, 2025
@galenbwill
Copy link
Contributor

Aarch64 intrinsic types are auto-generated from the ARM spec. This particular intrinsic has the following instruction pattern and type signature:

        FCVTZS Dd,Dn,#n
    int64_t vcvtd_n_s64_f64(float64_t a, const int n)

This is reflected in the LLIL, so I think this is an issue in the lifting from LLIL to MLIL, which is happening in the core, and is not specific to this intrinsic or architecture.

I will investigate further to see, but I agree with @xusheng6's triage that this might be a medium effort issue to fix.

@galenbwill
Copy link
Contributor

Correction: after some digging, I find that the problem is in the generated intrinsic code, as it is not setting the size of immediate argument values when providing the operands to the intrinsic call instruction.

While fixing this properly will require me to regenerate the neon_intrinsics.cpp for Aarch64, I can effectively fix it by changing the default argument value for the size parameter from 0 to 8 in add_input_imm.

This reduces the effort to Trivial (and Low for the proper fix), as it turns out not to be a problem in the core.

@galenbwill galenbwill added Effort: Trivial Issue should take < 1 day Lifting issues related to LLIL lifting and removed Effort: Medium Issue should take < 1 month Component: Core Issue needs changes to the core Core: MLIL Issue involves Medium Level IL State: Awaiting Triage Issue is waiting for more in-depth triage from a developer labels Jan 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Arch: ARM64 Issues with the AArch64 architecture plugin Effort: Trivial Issue should take < 1 day Impact: Medium Issue is impactful with a bad, or no, workaround Lifting issues related to LLIL lifting Type: Bug Issue is a non-crashing bug with repro steps
Projects
None yet
Development

When branches are created from issues, their pull requests are automatically linked.

4 participants