I'm testing several decompilers about struct reconstruction, given the following C
example:
struct S {
int x;
int y;
long z;
long t;
};
int foo(struct S s) {
return s.x + s.y + s.z + s.t;
}
int main() {
struct S s;
s.x = 10; s.y = 15; s.z = 20; s.t = 25;
return foo(s);
}
compiled without any optimization (even no stripping) using clang
as a 64-bit ELF, i.e. the ABI is System V x86-64
.
I've supposed that this is a trivial case so the decent decompilers should give correct results, they are not unfortunately.
Following result is given by IDA 7.4.191122
:
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // r8
__int64 v4; // r9
return foo(*(__int64 *)&argc, (__int64)argv, (__int64)envp, 20LL, v3, v4, 0xF0000000ALL, 20, 25);
}
__int64 __fastcall foo(__int64 a1, __int64 a2, __int64 a3, __int64 a4, __int64 a5, __int64 a6, __int64 a7, int a8, int a9)
{
return (unsigned int)(a9 + a8 + HIDWORD(a7) + a7);
}
Next, JEB 3.7.0
:
unsigned long main() {
return foo();
}
unsigned long foo() {
unsigned int v0 = v1 + v2;
return (unsigned long)(((unsigned int)(((long)v0 + v3 + v4)));
}
and Ghidra 9.1
void main(void)
{
foo();
return;
}
ulong foo(void)
{
int param_7;
undefined8 param_7_00;
int iStack000000000000000c;
long param_8;
long param_9;
return (param_7 + iStack000000000000000c) + param_8 + param_9 & 0xffffffff;
}
I cannot say that the results are "good", they are not even correct. Did I miss some configuration for these decompilers?
Edit: Because of request from @Tobias, I've added assembly code for the functions (and changed main
into bar
):
This is foo
:
0x0 55 push rbp
0x1 48 89 e5 mov rbp, rsp
0x4 48 8d 45 10 lea rax, [rbp+0x10]
0x8 8b 08 mov ecx, [rax]
0xa 03 48 08 add ecx, [rax+0x8]
0xd 48 63 d1 movsxd rdx, ecx
0x10 48 03 50 10 add rdx, [rax+0x10]
0x14 48 03 50 18 add rdx, [rax+0x18]
0x18 48 0f be 40 04 movsx rax, byte ptr [rax+0x4]
0x1d 48 01 c2 add rdx, rax
0x20 89 d0 mov eax, edx
0x22 5d pop rbp
0x23 c3 ret
and bar
:
0x30 55 push rbp
0x31 48 89 e5 mov rbp, rsp
0x34 48 83 ec 40 sub rsp, 0x40
0x38 c7 45 e0 0a 00 00 00 mov dword ptr [rbp-0x20], 0xa
0x3f c7 45 e8 0f 00 00 00 mov dword ptr [rbp-0x18], 0xf
0x46 48 c7 45 f0 14 00 00 00 mov qword ptr [rbp-0x10], 0x14
0x4e 48 c7 45 f8 19 00 00 00 mov qword ptr [rbp-0x8], 0x19
0x56 c6 45 e4 1e mov byte ptr [rbp-0x1c], 0x1e
0x5a 48 8d 45 e0 lea rax, [rbp-0x20]
0x5e 48 8b 08 mov rcx, [rax]
0x61 48 89 0c 24 mov [rsp], rcx
0x65 48 8b 48 08 mov rcx, [rax+0x8]
0x69 48 89 4c 24 08 mov [rsp+0x8], rcx
0x6e 48 8b 48 10 mov rcx, [rax+0x10]
0x72 48 89 4c 24 10 mov [rsp+0x10], rcx
0x77 48 8b 40 18 mov rax, [rax+0x18]
0x7b 48 89 44 24 18 mov [rsp+0x18], rax
0x80 e8 7b ff ff ff call foo
0x85 48 83 c4 40 add rsp, 0x40
0x89 5d pop rbp
0x8a c3 ret