Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decompile C code with debug info?

Java and Python byte code are relatively easy to decompile than compiled machine code generated by C/C++ compiler.

I am unable to find a convincing answer as to why the information from the -g option is insufficient for de-compilation, but sufficient for debugging? What is the extra stuff contained in Python/Java byte code, that makes decompilation easy?

like image 697
Saswat Padhi Avatar asked Aug 19 '26 16:08

Saswat Padhi


2 Answers

Here are some of the reasons for this:

  1. Java and Python bytecodes are relatively simple and high-level, whereas the instruction set of some CPUs (think x86) is fiendishly complicated.
  2. The bytecodes closely mimic the structure of the language for which they've been designed.
  3. When generating bytecodes, Java and Python perform do very little by way of optimization. This results in bytecodes that closely correspond to the structure of the original source code. A good optimizing C or C++ compiler is capable of producing assembly that's far removed from the original source code.
  4. There are few Java and Python compilers, and many C and C++ compilers. It's easier to produce a high-quality decompiler if you are targetting a single known compiler (or a small set of known compilers).
  5. Python and Java are relatively simple languages compared to C++ (this point doesn't apply to C).
  6. C++ templates present many challenges to quality decompilation (this point also doesn't apply to C).
  7. The C/C++ preprocessor.
  8. In Python, there is a one-to-one relationship between source files and bytecode files. In Java, the relatioship is one source to one or more bytecode files. In C and C++, the relationship is many-to-many, with a lot of overlap on the source front (think headers).
like image 178
NPE Avatar answered Aug 21 '26 07:08

NPE


I am unable to find a convincing answer as to why the information from the -g option is insufficient for de-compilation, but sufficient for debugging?

The debugging information basically contains only mapping between the addresses in the generated code and the source files line numbers. The debugger does not need to decompile code - it just shows you the original sources. If the source files are missing, debugger won't magically show them.

That said, presence of debugging info does make decompilation easier. If the debug info includes the layout of the used types and function prototypes, the decompiler can use it and provide a much more precise decompilation. In many cases, however, it will still likely be different from the original source.

For example, here's a function decompiled with the Hex-Rays decompiler without using the debug info:

int __stdcall sub_4050A0(int a1)
{
  int result; // eax@1

  result = a1;
  if ( *(_BYTE *)(a1 + 12) )
  {
    result = sub_404600(*(_DWORD *)a1);
    *(_BYTE *)(a1 + 12) = 0;
  }
  return result;
}

Since it does not know the type of a1, the accesses to its fields are represented as additions and casts.

And here's the same function after the symbol file has been loaded:

void __thiscall mytree::write_page(mytree *this, PAGE *src)
{
  if ( src->isChanged )
  {
    cache::set_changed(this->cache, src->baseAddr);
    src->isChanged = 0;
  }
}

You can see that it's been improved quite a lot.

As for why decompiling bytecode is usually easier, in addition to NPE's answer check also this.

like image 26
Igor Skochinsky Avatar answered Aug 21 '26 07:08

Igor Skochinsky



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!