Description
Version and Platform (required):
- Binary Ninja Version: 4.3.6844
- OS: Windows
- OS Version: 10
- CPU Architecture: x64
Bug Description:
I often see this pattern come up when looking at THUMB code:
push {r0, r1, r2, r3, r4, lr}
movs r4, #0
str r4, [sp, #4]
str r4, [sp, #8]
...
add sp, #0x10
pop {r4, pc}
There are 6 registers that are saved to the stack in the function prologue, but only 2 are actually restored in the epilogue. The r0/r1/r2/r3 stack slots are used as variables instead of actually being used to save/restore the registers. I guess the compiler may do this as an optimization to remove a sub sp, X
instruction.
Binja does not handle this pattern well, and it leads to code that looks like this in HLIL:
int32_t func(int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4)
int32_t var_c = arg4
int32_t var_10 = arg3
int32_t var_14 = arg2
var_14 = 0
var_10 = 0
...
The function is thought to have 4 arguments when it really only has 1.
Steps To Reproduce:
Can't share the binary that I encountered this in, but I did my best to create a minimal example for this (which may be a little contrived).
Please provide all steps required to reproduce the behavior:
- Create new window
- Paste in following bytes:
1fb505460024019401a800f005f8019c04eb050004b010bd052101607047
- Make thumb2 function
- See that
sub_0
is shown to have 2 arguments
Expected Behavior:
The function should not have any arguments appended if the stack variable the argument is written to is being reused as a regular variable.
A possible heuristic for this could be comparing the push/pop instructions of the function and considering any non-restored registers to not be arguments.