Provide support for large types
- Dominant language
- C++
- Stars
- 8.6k
- Forks
- 1k
- PR merge metrics
- No merged PRs in 30d
Description
Provide support for types that have size larger than word size of an architecture. Work with values of such type is specific for different ABIs. For instance on architectures that support passing arguments in registers (ARM, MIPS) are values passed in register pairs. Current implementation does not apply for such situations and thus some docompilations may result in incorrect code.
There are situation where by luck is generated correct code, for example on arm decompilation of such code...
```
int fun(uint64_t a, uint64_t b)
{
return a+b;
}
int main()
{
return fun(0, 1);
}
```
...would result in...
```
int32_t fun(int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6) {
return a3 + a1;
}
int main(int argc, char ** argv) {
return fun(0, 0, 1, 0, 0, 0);
}
```
...but if the input was...
```
int fun(uint32_t a, uint64_t b, uint32_t c)
{
return a+b+c;
}
int main()
{
return fun(0, 1, 2);
}
```
...then the decompilation would generate code...
```
int32_t fun(int32_t a1) {
int32_t v1;
return g1 + a1 + v1;
}
int main(int argc, char ** argv) {
g1 = 1;
return fun(0);
}
```
...which is incorrect. This is result of incorrect parameter analysis which does not take to account register pairs, that are used as parameter. For example on 32bit ARM are 64bit values stored in register pairs A0:A1, A2:A3, but the first register of a pair must have even number. The same behavior can be observer on MIPS as well.
Another situation is when function has return type of size larger than word size of architecture. Different ABIs use different techinques to return large values, for example register pairs. Current implementation of return type analysis does not expect that the result can be in something else than a one register. So code like this:
```
uint64_t fun()
{
return 4294967296;
}
int main()
{
uint64_t a = fun();
if (a > 0)
return 0;
return 1;
}
```
will result for example on ARM, MIPS and x86 in passing value in two registers but the result of decompilation of binaries is around the same on each architecture:
```
int32_t fun(void) {
return 0;
}
int main(int argc, char ** argv) {
int32_t v1 = fun();
return ((int32_t)((int64_t)v1 / 0x100000000) | v1) == 0;
}
```
Contributor guide
No contributing guide indexed for this repository
Research direction
No source files, tests, or entry points are named. Start by tracing the parameter and return type analysis described in the ARM, MIPS, and x86 examples, then compare the generated decompilations with the original functions. Done means large arguments and return values follow each target ABI, including register pairs and alignment, without producing incorrect code.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers, reverse-engineering
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100