Just a short post to show you the current state of the x64 decompiler. In fact, it already mostly works but we still have to solve some minor problems. Let us consider this source code:
struct color_t { short red; short green; short blue; short alpha; }; extern color_t lighten(color_t c); color_t func(int red, int green, int blue, int alpha) { color_t c; c.red = red; c.green = green; c.blue = blue; c.alpha = alpha; return lighten(c); }
After compilation we get the following binary code:
.text:0000000000000000 ?func@@YA?AUcolor_t@@HHHH@Z proc near .text:0000000000000000 .text:0000000000000000 c = color_t ptr -18h .text:0000000000000000 var_10 = qword ptr -10h .text:0000000000000000 arg_0 = dword ptr 8 .text:0000000000000000 arg_8 = dword ptr 10h .text:0000000000000000 arg_10 = dword ptr 18h .text:0000000000000000 arg_18 = dword ptr 20h .text:0000000000000000 .text:0000000000000000 mov [rsp+arg_18], r9d ; $LN3 .text:0000000000000005 mov [rsp+arg_10], r8d .text:000000000000000A mov [rsp+arg_8], edx .text:000000000000000E mov [rsp+arg_0], ecx .text:0000000000000012 sub rsp, 38h .text:0000000000000016 movzx eax, word ptr [rsp+38h+arg_0] .text:000000000000001B mov [rsp+38h+c.red], ax .text:0000000000000020 movzx eax, word ptr [rsp+38h+arg_8] .text:0000000000000025 mov [rsp+38h+c.green], ax .text:000000000000002A movzx eax, word ptr [rsp+38h+arg_10] .text:000000000000002F mov [rsp+38h+c.blue], ax .text:0000000000000034 movzx eax, word ptr [rsp+38h+arg_18] .text:0000000000000039 mov [rsp+38h+c.alpha], ax .text:000000000000003E mov rcx, qword ptr [rsp+38h+c.red] ; c .text:0000000000000043 call ?lighten@@YA?AUcolor_t@@U1@@Z ; lighten(color_t) .text:0000000000000048 mov [rsp+38h+var_10], rax .text:000000000000004D mov rax, [rsp+38h+var_10] .text:0000000000000052 add rsp, 38h .text:0000000000000056 retn .text:0000000000000056 ?func@@YA?AUcolor_t@@HHHH@Z endp
Please note that the c, which is a structure, is passed by value in 2 registers: rcx and rdx. We had to rework quite many things in the decompiler to support such variables (we call them scattered variables). However, the output was worth it:
color_t __fastcall func(__int16 cx0, __int16 dx0, __int16 r8_0, __int16 r9_0) { color_t c; c.red = cx0; c.green = dx0; c.blue = r8_0; c.alpha = r9_0; return lighten(c); }
There is still some work to be done, but it seems we solved most problematic issues. Stay tuned, there will be more decompiler news soon!