radareorg/r2ghidra

Why can r2ghidra not output the same code as ghidra in cutter

Opened this issue · 9 comments

When I used r2ghidra I found that its decompiled system does not output good decompiled code like ghidra in cutter. Here is a comparison of the two:
r2ghidra:
radare2-ghidra
cutter-ghidra:
cutter-ghidra

Cutter doesnt use radare2 or r2ghidra, those are different projects. So its expected to have different outputs, use iaito if you want the same behaviour with r2ghidra. i dont think any of those outputs is good.

The riz in has rz-ghidra and the r2 also has r2-ghidra. Is rz-ghidra different from r2-ghidra? Why does the same code produce a different output

For the average user, the discomplier is still very useful.

Yes r2ghidra is different than rz-ghidra. Its totslly not the same code. Also that depends on the ghidra code which both projects use different versions and also depend on the info from r2/rizin. So its normal that outputs differ

I see , I think rz-ghidra is better than r2ghidra in decomplie

Also, have you checked the “e r2ghidra.” Options? There are some values to tweak the output of the decompiler which may end up giving you the same or closer output. Note that dead code elimination is not enables by default in r2ghidra because in many situations ends up removing importsnt parts of the function. Probably not useful on trivial functions like this

I encounter the same issue, the decompiled code basically hard to read

for example, I compiled this code and analyse it with r2

decompiler produce

[0x00001070]> s main
[0x000011cb]> pdg

ulong main(void)

{
    ulong uStack_20;
    uchar auStack_18 [9];
    uchar auStack_f [7];
    
    *(*0x20 + -0x20) = 0x11e2;
    sym.imp.puts("Login: ");
    *(*0x20 + -0x18 + -8) = 0x11fa;
    sym.imp.fgets(&stack0xfffffffffffffff1, 7, _reloc.stdin);
    *(*0x20 + -0x18 + -8) = 0x1206;
    sym.check_password(&stack0xfffffffffffffff1);
    return 0;
}

while ghidra and rizin rz-ghidra gives more readable output

# rz-ghidra
undefined8 main(void)
{
    char *s;
    
    sym.imp.puts("Login: ");
    sym.imp.fgets(&s, 7, _reloc.stdin);
    sym.check_password((char *)&s);
    return 0;
}

# ghidra
undefined8 main(void)

{
  char local_f [7];
  
  puts("Login: ");
  fgets(local_f,7,stdin);
  check_password(local_f);
  return 0;
}

for more complicated binary it gets way harder to read.

Can you share this binary?

I attached the binary and the source code here, as well a second binary to compare the decompilation differences.
binaries.zip

Below is decompiled code of overflow binary

r2ghidra

$ r2 overflow
[0x000010b0]> aaa
[0x000010b0]> s sym.greet 
[0x00001199]> pdg

void sym.greet(ulong param_1)

{
    uint32_t uVar1;
    ulong uVar2;
    int64_t iVar3;
    uchar *puVar4;
    uchar *puVar5;
    ulong uStack_c0;
    uchar auStack_b8 [8];
    ulong uStack_b0;
    uchar auStack_a8 [140];
    uint32_t uStack_1c;
    
    uStack_b0 = param_1;
    *(*0x20 + -0xc0) = 0x11bb;
    uStack_1c = sym.imp.strlen(param_1);
    if (0x7e < uStack_1c && uStack_1c != 0x7f) {
        uStack_1c = 0x7f;
    }
    puVar4 = *0x20 + -0xb8;
    *(*0x20 + -0xb8 + -8) = 0x11e6;
    sym.imp.strcpy(&stack0xffffffffffffff58, _obj.what);
    uVar1 = uStack_1c;
    puVar5 = puVar4;
    *(puVar4 + -8) = 0x11fb;
    iVar3 = sym.imp.strlen(&stack0xffffffffffffff58);
    uVar2 = uStack_b0;
    *(puVar5 + -8) = 0x121b;
    sym.imp.strncpy(&stack0xffffffffffffff58 + iVar3, uVar2, uVar1);
    *(puVar5 + -8) = 0x122a;
    sym.imp.strdup(&stack0xffffffffffffff58);
    return;
}

rizin rz-ghidra

$ rizin overflow
[0x000010b0]> aaa
[0x000010b0]> s sym.greet 
[0x00001199]> pdg

// WARNING: Variable defined which should be unmapped: var_10h

void sym.greet(char *arg1)
{
    int64_t iVar1;
    int64_t iVar2;
    char *src;
    char *dest;
    size_t var_1ch;
    int64_t var_10h;
    
    var_1ch._0_4_ = sym.imp.strlen(arg1);
    if (0x7f < (uint32_t)var_1ch) {
        var_1ch._0_4_ = 0x7f;
    }
    sym.imp.strcpy(&dest, _obj.what);
    iVar2 = (int64_t)(int32_t)(uint32_t)var_1ch;
    iVar1 = sym.imp.strlen(&dest);
    sym.imp.strncpy((int64_t)&dest + iVar1, arg1, iVar2);
    sym.imp.strdup(&dest);
    return;
}