avast / avast/retdec

Call to function disappeared in decompiled code

Open
#1,000 3 comments 0 reactions 1 assignee Claimed by @PeterMatula View on GitHub
bug C-bin2llvmir
Dominant language
C++
Stars
8.6k
Forks
1k
PR merge metrics
No merged PRs in 30d

Description

The reproducing steps:

save the code below:

```cpp
#include
#include

void test1() {
printf("1");
exit(1);
}

void test2() {
printf("2");
}

int main(int argc, char *argv[]) {
test2();
return 0;
}
```

compile it and strip (strip is required otherwise retdec can correctly infer test2 as a function in early stages):

```shell
g++ bug.cpp -o bug_test && strip bug_test
```

use retdec-compiler:

```shell
./retdec-decompiler bug_test
```

In the result bug_test.c:

```cpp
// Address range: 0x1149 - 0x1161
// this is test1
int64_t function_1149(void) {
// 0x1149
putchar(49);
exit(1);
// UNREACHABLE
}

// Address range: 0x1161 - 0x1172
// this is test2
int64_t function_1161(void) {
// 0x1161
return putchar(50);
}

// Address range: 0x1172 - 0x118d
// this is main
int64_t function_1172(int64_t a1, int64_t a2) {
// 0x1172
return 0;
}
```

You can see the call to test2(function_1161) disappeared from main(function_1172).

After tracing the bug, it probably comes from:

https://github.com/avast/retdec/blob/18b434f02b64bfb85232525ca10a6026b5d1f54f/src/bin2llvmir/optimizations/decoder/decoder.cpp#L514-L544

The debugger says that tFnc and tTb are null pointers. It comes from:

https://github.com/avast/retdec/blob/18b434f02b64bfb85232525ca10a6026b5d1f54f/src/bin2llvmir/optimizations/decoder/ir_modifications.cpp#L211-L216

Where the code thinks it is in the middle of a basic block and not splitting it. The debug output says:

```
processing : 0x1172 (LEFTOVER) (CS_MODE_LITTLE_ENDIAN, CS_MODE_64)
found range = <0x1172, 0x1205)
S: createFunction() @ 0x1172
F: splitFunctionOn() @ 0x1172
translating = 0x1172
translating = 0x1173
translating = 0x1176
translating = 0x117a
translating = 0x117d
translating = 0x1181
S: ASM @ 0x1161
F: getBasicBlockContainingAddress() @ 0x1161
translating = 0x1186
translating = 0x118b
translating = 0x118c
```

The basic block map for reference:

```
(gdb) p/x _addr2bb
$5 = std::map with 30 elements = {[{address = 0x1003}] = 0x55555cbdfc70, [{address = 0x1014}] = 0x55555a7aa6c0, [{
address = 0x1016}] = 0x55555a781dd0, [{address = 0x1030}] = 0x55555cbdc650, [{address = 0x1040}] = 0x55555cbd68d0, [{
address = 0x1050}] = 0x555558984210, [{address = 0x1053}] = 0x55555a7adc20, [{address = 0x1093}] = 0x55555a7ae270, [{
address = 0x109f}] = 0x55555cbdff50, [{address = 0x10a8}] = 0x55555a7aa7a0, [{address = 0x10b0}] = 0x55555cbde840, [{
address = 0x10d4}] = 0x55555cbdfb00, [{address = 0x10e0}] = 0x55555a7ac860, [{address = 0x10e8}] = 0x55555a7ae220, [{
address = 0x10f3}] = 0x55555cbdfc20, [{address = 0x10fd}] = 0x55555cbdffa0, [{address = 0x110b}] = 0x55555cbd04f0, [{
address = 0x1118}] = 0x55555cbcc4d0, [{address = 0x111d}] = 0x55555cbd0770, [{address = 0x1130}] = 0x55555a78a880, [{
address = 0x1143}] = 0x55555cbd60c0, [{address = 0x1149}] = 0x55555cbd6110, [{address = 0x1172}] = 0x55555cbde770, [{
address = 0x3fd8}] = 0x55555a781e20, [{address = 0x3fe0}] = 0x55555a7aa2d0, [{address = 0x3fe8}] = 0x55555a7ab190, [{
address = 0x3ff0}] = 0x55555a7ad4f0, [{address = 0x3ff8}] = 0x55555cbdf9e0, [{address = 0x4018}] = 0x55555cbdfe30, [{
address = 0x4020}] = 0x55555a78a410}

```

FWIW function_1149 is placed right before function_1161 in assembly:

```asm
// test1
1149: 55 push %rbp
114a: 48 89 e5 mov %rsp,%rbp
114d: bf 31 00 00 00 mov $0x31,%edi
1152: e8 e9 fe ff ff call 1040
1157: bf 01 00 00 00 mov $0x1,%edi
115c: e8 cf fe ff ff call 1030
// test2
1161: 55 push %rbp
1162: 48 89 e5 mov %rsp,%rbp
1165: bf 32 00 00 00 mov $0x32,%edi
116a: e8 d1 fe ff ff call 1040
116f: 90 nop
1170: 5d pop %rbp
1171: c3 ret
// main
1172: 55 push %rbp
1173: 48 89 e5 mov %rsp,%rbp
1176: 48 83 ec 10 sub $0x10,%rsp
117a: 89 7d fc mov %edi,-0x4(%rbp)
117d: 48 89 75 f0 mov %rsi,-0x10(%rbp)
1181: e8 db ff ff ff call 1161
1186: b8 00 00 00 00 mov $0x0,%eax
118b: c9 leave
118c: c3 ret
```

The function at 1149 ends with an unreachable call instead of ret. And retdec is not recognizing 0x1161 as a basic block. Thus retdec is not working properly.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.