avast / avast/retdec

Wrong LLVM IR parameters after decompilation

Open
#269 1 comment 0 reactions 0 assignees View on GitHub
bug C-bin2llvmir P-output
Dominant language
C++
Stars
8.6k
Forks
1k
PR merge metrics
No merged PRs in 30d

Description

I noticed a problem while decompiling simple functions in different files (I pulled and build RetDec an hour before creating the issue for being certain to have the latest version).

Here is the code I tried to decompile:

**simple.c**
```c
uint32_t simple_add(uint32_t *a, uint32_t *b) {
return *a + *b;
}
```

**main.c**
```c
#include "simple.h"

int main(int argc, char** argv) {
uint32_t a, b;

a = atoi(argv[1]);
b = atoi(argv[2]);

return simple_add(&a, &b);
}
```

The code was compiled with the command (GCC 6.3.0 20170516):
```bash
gcc -std=c99 -Wall -Werror -pedantic -m32 main.c simple.c -o main
```

Then I invoked the following command to decompile the binary:
```bash
./retdec-decompiler.sh --stop-after bin2llvmir --select-functions simple_add ./main
```

Here's the LLVM IR output code after decompilation:

**main.c.backend.ll**
```LLVM
source_filename = "test"
target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"

define i32 @simple_add(i32* %arg1, i32 %arg2) local_unnamed_addr {
entry:
%v0_593 = call i32 @__x86.get_pc_thunk.ax()
%v2_5a0 = load i32, i32* %arg1, align 4
%v1_5a5 = inttoptr i32 %arg2 to i32*
%v2_5a5 = load i32, i32* %v1_5a5, align 4
%v2_5a7 = add i32 %v2_5a5, %v2_5a0
ret i32 %v2_5a7
}

declare i32 @__x86.get_pc_thunk.ax() local_unnamed_addr

declare i32 @__decompiler_undefined_function_0() local_unnamed_addr
```

As you can see, the decompiler interpreted the first parameter as an `i32*`, which is ok but the second one is interpreted as an `i32` and then is cast to an `i32*` in the method's body. I also tried with three parameters and the result is the same: only the first parameter is interpreted correctly.

Did I miss something or is it a bug?

Thanks in advance for your time.

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce the issue with simple.c and main.c using the shown GCC and retdec-decompiler.sh --stop-after bin2llvmir command, then inspect main.c.backend.ll. Start at the bin2llvmir parameter-recovery path and compare the recovered types for simple_add; done means each pointer argument is represented as a pointer in the function signature without an incorrect integer-to-pointer cast.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, cpp
Domain
compilers, reverse-engineering
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.