|
2010/02/01
|
Welcome to Hex-Rays v1.2, with intrinsic function support.
This release adds all intrinsic functions defined by Microsoft and Intel
(with some exceptions), SSE scalar floatiing point support, local cross
references, and other improvements. Please refer to the comparison page for side-by-side examples.
BIG NEWS
- + SSE scalar floating point support
- + Support for intrinsic functions (the
decompiler recognizes more than 500 intrinsic functions from Microsoft
and Intel)
- + New microcode preoptimization algorithm with O(n)
complexity. It is much faster, especially on long basic blocks.
For long basic blocks, it really makes a big difference,
the analysis can be faster hundreds of times because the long
basic block immediately gets optimized into something small
without using the main propagation mechanism, which has
O(n**2) complexity.
- + Local cross reference commands
NITPICKY DETAILS
FIXES
- BUGFIX: __thiscall calls in the very first block of a function that also had the __thiscall calling convention were not detected
- BUGFIX: bcc __fastcall functions returning a big structure were decompiled incorrectly (the hidden argument was located wrongly)
- BUGFIX: calls were sometimes propagated too far
- BUGFIX: could crash trying to decompile a fp constant reference
- BUGFIX: decompilation of fragmented functions with fpu instructions could fail in some cases
- BUGFIX: decompiler could interr because the type of the ternary operator was calculated inconsistently
- BUGFIX: decompiler could interr trying to handle 64-bit comparisons
- BUGFIX: decompiler could throw an exception if the cursor was positioned on some statement labels
- BUGFIX: decompiler would interr if fpu conditional jump was optimized into unconditional jump
- BUGFIX: div_power_2() rule could produce incorrect results
- BUGFIX: fcomi and similar instructions were decompiled incorrectly
- BUGFIX: fixed a quite subtle bug with nameless structs: a reference like p->gt;4.field (4 is the name of a nameless structure) could be split in the middle by the cpa module. this would lead to interr later because a reference like p->gt;4 is not good
- BUGFIX: fixed a rare interr that could happen on complex functions (interr 656)
- BUGFIX: functions tails belonging to multiple parents could cause an interr
- BUGFIX: it was impossible to specify the representation of case values for synthetic switches (converted from a sequence of if's)
- BUGFIX: it was still possible to convert numbers to 128-bit enums and get an interr
- BUGFIX: LODWORD/HIDWORD macros were not used by the decompiler
- BUGFIX: lvar allocation could crash
- BUGFIX: lvar allocation could incorrectly reuse an old variable instead of creating a new one (rarely happened upon partial references to wide variables)
- BUGFIX: non-zero deltas in user-defined offset were ignored by the decompiler
- BUGFIX: precedence rules for * and post ++/-- operators were incorrect. the decompiler would generate **x++ instead of *(*x)++
- BUGFIX: some 64-bit additions would be handled incorrectly (well, at least in theory)
- BUGFIX: some 64-bit casts were erroneously removed: int64(i32)*j32 =>gt; i32*j32
- BUGFIX: some nice constants that correspond to the assembly listing could still not be modified (converted to hex, etc)
- BUGFIX: some signed divisions by a negative constant were not recognized
- BUGFIX: the decompiler could use stale guessed type information because it was not updating its internal type storage on all database modifications
- BUGFIX: the propagation could yield an incorrect result in some rare cases
- BUGFIX: the representation of 'magic' division divisors could not be changed by the user
|
|
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
|