Decompiler Changelog

Free updates can be requested by selecting from Edit, Plugins, Hex-Rays, Check for Updates in IDA Pro. Page for manual requests is here.

The order form can be downloaded here
2009/06/12

Welcome to Hex-Rays v1.1, with floating point support. This release adds a major new feature: floating point support, and numerous other improvements. Please refer to the comparison page for side-by-side examples.

BIG NEWS

  • + floating point support
  • + better 64-bit arithmetics support (instruction pairs are recognized better)
  • + new analysis: live ranges of stack variables; reused slots are detected and properly handled (if not aliased)
  • + __usercall with ellipsis is supported

NITPICKY DETAILS

  • + slightly modified attachment of block comments. the new method is slightly better but the existing block comments on multiline binary operations may move from one operand to another:
  • + decompiler distinguishes alisable and restricted (non-aliasable memory)
  • + delphi overflow and range checks are hidden from the output
  • + the "reset types" command can reset local or global types
  • + slightly more aggressive stkvar elimination; unfortunately we can not eliminate unused stkvars completely in the presence of unknown or guessed function calls - if a function argument list is detected incorrectly, we risk deleting useful code
  • + added rule: x=y,x => (x=y) != 0
  • + decompiler generates less partial types
  • + added parsing of function prototype line
  • + local variable declarations are sorted: first are register variables sorted by basic blocks, then stack variables sorted by frame offets
  • + added FOR-2 rule to create more for-loops
  • + improved handling of 64bit operations
  • + improved the decompiler engine to eliminate common subexpressions in some special cases
  • + more aggressive cast removal: if the result of add/sub and similar operations is finally truncated, remove truncation casts for operands
  • + added COERCE_... helper functions to convert int/float types when regular cast operations are not enough
  • + better handling of 64-bit values in vararg arguments
  • + better type casts for object references (decompiler was resolving types when it was not really necessary and replacing, e.g. LPSTR by char *)

FIXES

  • BUGFIX: WHILE-5 rule could duplicate a label and then interr
  • BUGFIX: tail calls to noreturn function were not marked as such
  • BUGFIX: right-clicking on the very first { could crash the decompiler
  • BUGFIX: "create new struct type" could create a type with void fields
  • BUGFIX: jo/jno instructions could hide some code from the listing
  • BUGFIX: decompiler would interr on too wide enums (>128bits)
  • BUGFIX: jo/jno instruction could hide executable code; added special handling for them and for delphi overflow checks
  • BUGFIX: decompiler could interr trying to create a variable of va_list type
  • BUGFIX: wrong decompilation output could be generated in some rare cases
  • BUGFIX: some sign-extension casts were missing
  • BUGFIX: array[(uchar)i8] could erroneously be represented as array[i8]
  • BUGFIX: decompiler was considering everything after any // in the output as comments
  • BUGFIX: rule19 to recognize 64bit multiplications could occasionally create wrong code and interr
  • BUGFIX: control flow after memset/memcpy could be rendered incorrectly
  • BUGFIX: decompiler could create a function that returns a value in edx register without returning anything in eax register
  • BUGFIX: decompiler could crash on some inputs
2009/01/29

Maintenance release of the decompiler.
We decided to release an intermediate version with all accumulated improvements and bugfixes while still continuing to work on the floating point support.

  • + added block comments
  • + added support for function comments
  • + added command to hide cast operators from the output (hotkey is \)
  • + added warnings. they can be suppressed by WARNS1 parameter in hexrays.cfg
  • + derived types are saved into the database: now decompilation results should not differ between sessions
  • + improved the speed of batch decompilation: better handling of decompilation queue
  • + references to " r" and " s" special stack frame members are renamed to "retaddr" and "savedregs"
  • + mach-o: __cls_refs and __message_refs sections are handled in a special way
  • + added special handling for elf .got sections
  • + added special handling for mach-o __pointers section
  • + reserved words can not be used as local variable names. the function name is rejected too
  • + if the user requested a bitfield for a constant, use it even if some bits have no corresponding symbolic names; these bits are printed in hex
  • + added rule: *(x+y) => x[y]
  • + sdk: added get_line_item() to facilitate mapping of line items
  • + sdk: added hxe_text_ready and hxe_print_func events
  • bugfix: expressions with pointers to arrays were suboptimal; if such types were used for function arguments, the output would be wrong
  • bugfix: small (4 byte) arrays could be used as scalars in the output, which was wrong
  • bugfix: if instruction bytes were patched without reanalyzing them, the decompiler could interr
  • bugfix: error message for 16bit applications was wrong
  • bugfix: decompiler could create fastcall functions with __int64 register arguments
  • bugfix: tail call to unknown function could lead to interr
  • bugfix: the decompiler could crash in some exceptional circumstances
  • bugfix: fixed a typo that could lead to a crash
  • bugfix: if a funcarg was also represeting the return value, the function prototype could be modified during analysis
  • bugfix: could interr on a linux syscall if it was the last instruction of the function
  • bugfix: if the user modified a structure field type, it would be detected by the decompiler
  • bugfix: mul64 recognizer could create an interr
2008/09/23

The decompiler is more robust and generates better output.
Check out the sample snippets!

  • Improved handling of nest structure/array references. Example:
                     mov     eax, [ebp+arg_0]
                     mov     edx, [eax+8]
                     lea     edx, [edx+edx*2]
                     mov     eax, [eax+4]
                     mov     ecx, [eax+edx*8+10h]
                     mov     eax, [ecx+1Ch]
    is converted into the following one line:
    void *__cdecl get_entry_addr(graph_t *g)
    {
      return g->nodes[g->entry_idx].attrs[1].value;
    }
  • Better recognition of int32->int64 conversions. Before:
       if ( i > 2 )
        {
          *(_DWORD *)&v3 = i - 2;
          *((_DWORD *)&v3 + 1) = (i - 2) >> 31;
          if ( !(v3 % 3) )
            buf[i] -= -0xFFFFFFB4u;
        }
    After:
          if ( !((i - 2) % 3) )
            buf[i] -= -0xB4u;
  • Less truncation casts since they just make the code more difficult to read. Before:
    byte_10098A1[result] = (unsigned __int8)byte_10098A1[result] | 0x10;
    After:
    byte_10098A1[result] |= 0x10u;
  • Better local variable allocation. Before:
    if ( result->f0 < 1 )
    {
      LOWORD(this) = result->f0;
      this = (char *)this + 12;
      result->f0 = (_WORD)this;
    }
    if ( result->f0 > 12 )
    {
      LOWORD(this) = result->f0;
      result->f0 = (unsigned int)((char *)this - 12);
    }
    After:
    if ( result->f0 < 1 )
      result->f0 += 12;
    if ( result->f0 > 12 )
      result->f0 -= 12;
  • Added support for tail calls to vararg functions that do not use the input arguments
  • Added support for uninitialized structures passed by value
  • 2-way (or less) switch statements are supported
  • Calls to alloca() are displayed in the output. unfortunately, the return value is not linked to the rest of the output
  • Better handling of non-int size arithmetics
  • Better support of the cpuid insn
  • Decompiler uses structure offset information if present in the disassembler listing
  • Decompiler does not generate casts for the right operand of a shift operation
  • If the decompiler detects that a function call uses uninitialized variables, it may correct the callee's prototype on the fly (unless it has been specified by the user)
  • Improved the logic that handles representation of numbers: more numbers are handled
  • More robust handling of jumpout cases
  • References to global names hidden by a local name are prefixed with ::
  • (x >> n1) >> n2 is optimized into x >> (n1+n2)
  • Negated hex numbers like 0xFFFFFFB5 are displayed in short form (0xB5) if the meaning of the code stays the same
  • bugfix: a __thiscall prototype without any arguments could crash the decompiler
  • bugfix: decompiler could dereference arrays of pointers to udts too many times (it could generate var[idx]->field instead of simply var[idx])
  • bugfix: decompiler could loop infinitely if a reference to wrongly defined type was present (for example, "struct xxx" while the type library has "enum xxx", not struct)
  • bugfix: decompiler was offering new structure types without considering the default structure alignment; for packed structures, the result could be wrong
  • bugfix: functions with invalid basic blocks could be decompiled incompletely (some input code would not be decompiled at all)
  • bugfix: if the result of a builtin function was truncated before the use, the function would not be recognized
  • bugfix: in some rare cases the value propagation could produce wrong results
  • bugfix: instruction combination algorithm could produce incorrect results
  • bugfix: j[er]cxz could not be decompiled if the operand size and address size were different
  • bugfix: references to an array element that was pointed by a structure field were represented incorrectly
  • bugfix: some unsupported instructions were causing lvar allocation failure
  • bugfix: the decompiler would wrongly eliminate the cast in "(int64)x << s"
  • bugfix: the same name could be used as a local variable name and a function argument name at the same time
  • bugfix: many interrs (mostly rare and difficult to reproduce) have been fixed
2008/05/08

No more invalid basic blocks

  • + added possiblity to decompile functions with wrong basic blocks
    (see hexrays.cfg; is partilly wrong output is better than no output?)
  • + pushf/popf pairs are eliminated in basic blocks
  • + rdtsc instruction is converted to RDTSC() call
  • + more tail calls are recognized
  • + prefer to preserve type names in type deductions
  • + better heuristics to determine the number of tail call arguments
  • + do not combine the frame pointer with any other register
  • + improved display of arrays of nested structures
  • + slightly improved local variable allocation
  • + added support for 1-target switch idioms (curiously enough, they do exist)
  • bugfix: decompiler could handle functions with the stack of 256kb max (docs states 1mb limit)
  • bugfix: some ellipsis functions were losing '...' when decompiled multiple times
  • bugfix: "jmp self" used as a case of a switch statement would lead to interr: switch(..) { .. case: while(1); ..}
  • bugfix: functions with tail calls to nonreturning functions would cause interr
  • bugfix: check that "void *" is 4 bytes; otherwise there will be an interr
  • bugfix: using tab to switch to a problematic function that could not be decompiled would leave the existing pseudocode window empty; this could lead to a crash later
  • bugfix: decompiler could destroy structure instances or data with user-defined type information
  • bugfix: complex nested structure member references could be displayed wrongly
2008/02/17

Easy structure types(click for more info)

  • +new command: build a new structure type based on the access patterns from pseudocode
  • +new command: select an existing struct from the list (convert to struct *)
  • +new command: reset a pointer type
  • +new command: "Edit, Comment, Delete pseudocode comments" to delete pseudocode comments from the disassembly listing
  • +new command: "Edit, Other, Reset decompiler type information" to reset lvar types hindering the decompilation
  • +new command: "Edit, Other, Toggle skippable instructions" to handle misidentified prolog/epilog instructions
  • + more complex logic to select the better representation from ptr and &ptr->field0; if we can avoid a cast by adding a reference to zero offset field, then we do it
  • + Tab key behaviour in the disassembly view is slightly different - if the current location does not belong to a function, it simply switches to the pseudocode window
  • bugfix: some references to low part of a variable of a pointer type were represented incorrectly (ok: LOBYTE(v), bad: &v->field0)
  • bugfix: decompiler was too aggressively deleting indirectly accessed stkvars
  • bugfix: / in the pseudocode window could work as "add comments to disassembly view"
  • bugfix: / invoked from the disassembly view could crash if repeated a few times
  • bugfix: structure fields could not be manipulated (renamed or changed the type) in the expressions like ptr->field
  • bugfix: a random crash could occur in very rare cases
  • bugfix: shift left followed by shift right could erroneously converted into a division operation in some cases
2008/01/02

Better user interface and improved robustness (click for more info)

  • + multiple pseudocode windows can be opened
  • + new command: copy c text to disassembly window (available from the right-click menu)
  • + new command: the tab key toggles between the disassembly and pseudocode windows
  • + new command: hide/unhide statements (if,loops,switch,blocks)
  • + new command: jump to xref; since the pseudocode addresses do not map exactly to disassembly addresses, the decompiler jump to the nearest address if an exact match can not be found
  • + status line of pseudocode window displays the name of the current function
  • + spoiled<> keyword is supported by the decompiler (maybe there are some cases when it is ignored, requires more thourough testing)
  • + more intelligent handling of tail calls
  • + more intelligent detection of thiscall/fastcall function types
  • + improved detection of saved eax/edx pairs: now such functions are correctly detected as returning 'void'
  • bugfix: delieberately obfucsated code could cause interrs
  • bugfix: wrong sp trace could lead to interr; now it leads to 'lvar allocation failure'
  • bugfix: output code for the SF flag was incorrect. the code was "x<y" while it must be "(x-y)<0"
  • bugfix: attempt to decompile an uncompletely analyzed function could lead to interr (because of incorrect sp values); now decompiler gracefully fails in the situation
  • bugfix: function pointers can not be subtracted or compared but hexrays was doing it; added necessary casts to the output
  • bugfix: some linux calls (accepting arrays as parameters) could cause interr
  • bugfix: if the decompiled code was accessing undefined registers, the decompiler could interr
2007/11/28
  • + sdk: added reference manual; new functions; sample plugnis
    See a sample plugin in action
  • + added invert sign command
  • + added rule: (type)&x[0] => (type)x if x is not a structure field
  • + double click on stkvar opens the function frame window
  • + linux kernel get_current() macro is recognized
  • + more aggressive variable propagation across function calls
  • + more intelligent approach to instruction combining: we do not lump together array elements
  • + sdk: user settings for any function are available without decompiling the function
  • + stkvar types are guessed more accurately
  • + the 'space' button jumps to the beginning of the current function if could not determine the exact instruction corresponding to the current item
  • + added support for the 'ud2' instruction
  • ida v5.1 does not support arrays of in-place structure definitions, the decompiler takes this into account
  • removed CHECKMEM bit from interactive operation
  • bugfix: '64bit app' flag in 32bit databases could cause an interr
  • bugfix: 64bit arithmetic recognizer could divide by zero in some cases
  • bugfix: in some cases N could be lost in expressions like "ptr+var+N"
  • bugfix: reference to the first element of an array sometimes was not represented correctly
  • bugfix: references to external symbols with addends were not handled properly (relevant only to object files)
  • bugfix: some compiler helper functions could be missed because of the unexpected number of underscores in the name. now all underscores at the name start are ignored
  • bugfix: structure/array reconstruction could cause an interr
  • bugfix: unused structure types could be created
  • bugfix: wrong function type (with overlapping input arguments) could be created
2007/10/25
  • + Hex-Rays SDK v1.0 has been released
    The current state and possible uses: click here
    To see a sample plugin: click here
  • + added config file hexrays.cfg
    Background colors and various indentations can be configured
  • + added support for bitfields
    For example, you can convert this:
      v2 = CreateFileA(lpFileName, 0xC0000000u, 3u, 0, 3u, 0x27u, 0);
            
    into this:
      v2 = CreateFileA(
             lpFileName,
             GENERIC_READ|GENERIC_WRITE,
             FILE_SHARE_WRITE|FILE_SHARE_READ,
             0,
             OPEN_EXISTING,
             FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM
             |FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_READONLY,
             0);
            
  • + multiplications by big powers of 2 are replaced by shifts
    Before:
    v12 = 256 * v9->x1 + 65536 * v9->x2 + 16777216 * v9->x3 + v9->x0;
            
    After:
    v12 = (v9->x1 << 8) + (v9->x2 << 16) + (v9->x3 << 24) + v9->x0;
            
  • + improved local variable allocation
    Almost all allocation failures have disappeared
  • + more aggressive stack variable assignment elimination
    Useless assignments to stack variables (mostly because of push instructions that allocate the stack space) are eliminated from the output
  • + use non-trivial label names from the diassembly in the pseudocode window
    Before:
    LABEL_20:
      cleanup(&v16);
      return v18;
            
    After:
    locret:
      cleanup(&v16);
      return v18;
            
  • bugfix: fixed a minor and rare memory leak (lvar_ref_t)
2007/10/11
  • + added support for one yet another type of sparse switches
  • + added handling of signed comparisons with a negative number
  • + stkvars of structure type were used a byte arrays; now the decompiler knows to use their real type
  • + switch case number formats can be specified by the user
  • + minor optimization: switch ( x-N ) => switch ( N )
  • bugfix: decompiler could produce wrong output if bit test and manipulation instructions were present (bt,btc,btr,bts,bsr,bsf) because it was not taking into account that the processor condition codes were modified
  • bugfix: batch decompilation of all functions would crash with an external exception in some rare cases (logic flaw in the preparation of the function list)
  • bugfix: the default .c output file name was based on the name of the first function instead of the input file name
  • bugfix: it was not possible to create a new database and run decompiler in the batch mode; two step action was required: first create the database and analyze it, then run the decompiler