|
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
|