Version and Platform (required):
- Binary Ninja Version: 5.4.9875-dev (86d1e1ad)
- Edition: Commercial
- OS: Debian Linux
- OS Version: unstable
- CPU Architecture: x86_64
Bug Description:
In the Apple arm64 ABI, "Function arguments may consume slots on the stack that are not multiples of 8 bytes." Thus, for example, a series of 32-bit arguments on the stack is placed with no padding between arguments. Binary Ninja mishandles this… sometimes.
Steps To Reproduce:
Test case: test.zip
Both files (optimized.o and unoptimized.o) are built from the same source code:
extern void test(int x0, int x1, int x2, int x3, int x4, int x5, int x6, int x7, int sp0, int sp4, int sp8, int spC);
void go() {
test(0, 1, 2, 3, 4, 5, 6, 7, 0x100, 0x104, 0x108, 0x10c);
}
To reproduce, load one of the objects, create a function for go (for some reason it is not created automatically; another bug?), and set the type of test to match the source code.
Expected behavior: Both files should show test being called with the correct arguments.
Actual behavior: unoptimized.o is correct, but optimized.o shows:
0040004c return _test(x0: 0, x1: 1, x2: 2, x3: 3, x4: 4, x5: 5, x6: 6, x7: 7,
0040004c sp0: 0x10400000100, sp4: 0x10c00000108)
The difference between the binaries is that optimized.o was built with -O3 while unoptimized.o was built with -O0. As a result, optimized.o packs the arguments into 64-bit registers before storing them to the stack:
0040000c 082180d2 mov x8, #0x108
00400010 8821c0f2 movk x8, #0x10c, lsl #0x20 {0x10c00000108}
00400014 092080d2 mov x9, #0x100
00400018 8920c0f2 movk x9, #0x104, lsl #0x20 {0x10400000100}
0040001c e92300a9 stp x9, x8, [sp] {var_20} {var_18} {0x10400000100} {0x10c00000108}
Whereas optimized.o just stores the arguments one at a time:
00400010 08208052 mov w8, #0x100
00400014 280100b9 str w8, [x9 {var_20}] {0x100}
00400018 88208052 mov w8, #0x104
0040001c 280500b9 str w8, [x9, #0x4 {var_1c}] {0x104}
00400020 08218052 mov w8, #0x108
00400024 280900b9 str w8, [x9, #0x8 {var_18}] {0x108}
00400028 88218052 mov w8, #0x10c
0040002c 280d00b9 str w8, [x9, #0xc {var_14}] {0x10c}
The actual stack layout is the same. But for some reason BN treats these differently.
Version and Platform (required):
Bug Description:
In the Apple arm64 ABI, "Function arguments may consume slots on the stack that are not multiples of 8 bytes." Thus, for example, a series of 32-bit arguments on the stack is placed with no padding between arguments. Binary Ninja mishandles this… sometimes.
Steps To Reproduce:
Test case: test.zip
Both files (
optimized.oandunoptimized.o) are built from the same source code:To reproduce, load one of the objects, create a function for
go(for some reason it is not created automatically; another bug?), and set the type oftestto match the source code.Expected behavior: Both files should show
testbeing called with the correct arguments.Actual behavior:
unoptimized.ois correct, butoptimized.oshows:The difference between the binaries is that
optimized.owas built with-O3whileunoptimized.owas built with-O0. As a result,optimized.opacks the arguments into 64-bit registers before storing them to the stack:Whereas
optimized.ojust stores the arguments one at a time:The actual stack layout is the same. But for some reason BN treats these differently.