Up until Dart SDK v3.4.0, Dart was using an uncommon calling convention where all arguments for a function were passed on the stack [see my previous article] and [here].
Today, as I was peering into the disassembly of an app, I noticed this has changed! Dart now uses a standard calling convention, where the first few arguments are passed in specific registers and only if there are more they are pushed on the stack.
On Arm 64, registers r1 to r7 are used, with the exception of r4.
struct DartCallingConvention {
static constexpr Register kCpuRegistersForArgs[] = {R1, R2, R3, R5, R6, R7};
static constexpr FpuRegister kFpuRegistersForArgs[] = {V0, V1, V2,
V3, V4, V5};
};
In the assembly below, Radare2 shows the assembly to call a method named nextGame()
, with the following source code:
class ColorMemoryState extends State<ColorMemoryStateful>{
...
void nextGame(String buttonText, String msg) {
...
}
}
As nextGame
is applied an object, as usual, a reference to the current object this
is provided as first argument in x1
.
x1
is computed through the first 2 instructions (ldur and add), which actually achieve what is called as pointer decompression. To keep smaller pointers, Dart often uses compressed pointers where only the lower 32 bits of a pointer are kept in memory. To be used, the pointer must be decompressed. Here, the address of x0+0x0f
contains the compressed address. The upper bits are added in the second instruction (add
) through x28 << 32 (x28, lsl 32
).
x2
contains the address of x27+0x7b40
. On Arm64, Dart uses x27
as a special register to access the Object Pool. The Object Pool contains frequently used objects, constants and immediates. In this case, it will get a string for a button.
Similarly, x3
contains the address of another string, loaded from x27+0x7b48
. It is the msg
argument.
So what?
Disassemblers were often confused by this initial unknown convention. This change is likely to make it easier for them.
References:
- Patch that changes the calling convention: https://github.com/dart-lang/sdk/commit/2dae577c676a16afe99f9a7058de51ef381b983f
- A. Apvrille, “Dart and Flutter Reverse Engineering Reference”, July 19, 2024
Thanks to @Julemand101 and @KayZ for their helpful input on Dart community Discord server.
— Cryptax