Hmily 发表于 2009-8-21 16:21

Hex-Rays v1.1 have been released

Hex-Rays v1.1 have been releasedWelcome 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 supportedNITPICKY 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[*]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


Hex-Rays v1.1 Comparison PageWelcome to the Hex-Rays Decompiler v1.1 comparison page! Below you will find side-by-side comparisons of Hex-Rays v1.0 and v1.1 outputs. Please maximize the window too see both columns simultaneously.
The following original exhibits are displayed on this page:

[*]More aggressive variable elimination [*]More for-loops [*]Better recognition of 64-bit idioms [*]Better recognition of 64-bit idioms, example 2 [*]Floating point instructions [*]Better recognition of built-in functions [*]More aggressive value propagation [*]New algorithm to detect function arguments [*]Implicit value propagation NOTE: these are just some selected examples, that can be illustrated as a side-by-side difference. Hex-Rays Decompiler v1.1 includes are many other improvements and new features that are not mentioned on this page - simply because there was nothing to compare them with. The most notable new feature is support of floating point instructions, among other things. Please refer to the news page for more details.

More aggressive variable elimination
HRESULT __stdcall AtlMarshalPtrInProc(LPUNKNOWN pUnk, const IID *riid, LPSTREAM *ppstm) { HRESULT v3; // edi@1 LPSTREAM *v4; // esi@1 HRESULT v6; // eax@1 HRESULT v7; // eax@2 v4 = ppstm; v6 = CreateStreamOnHGlobal(0, 1, ppstm); v3 = v6; if ( v6 >= 0 ) { v7 = CoMarshalInterface(*v4, riid, pUnk, 3u, 0, 1u); v3 = v7; if ( v7 < 0 ) { (*v4)->lpVtbl->Release(*v4); *v4 = 0;
}
} return v3;
} HRESULT __stdcall AtlMarshalPtrInProc(LPUNKNOWN pUnk, const IID *riid, LPSTREAM *ppstm) { HRESULT v3; // edi@1 v3 = CreateStreamOnHGlobal(0, 1, ppstm); if ( v3 >= 0 ) { v3 = CoMarshalInterface(*ppstm, riid, pUnk, 3u, 0, 1u); if ( v3 < 0 ) { (*ppstm)->lpVtbl->Release(*ppstm); *ppstm = 0;
}
} return v3;
} We improved the decompiler engine to eliminate more variables. This means less useless assignments, shorter and more readable code.

More for-loops
j = 0; while ( j < 5 ) { v3 = 1 << j; tbl2[j + 5 * i] = ((1 << j) & v1) == 1 << j; ++j;
} for ( j = 0; j < 5; ++j ) { v3 = 1 << j; tbl2[j + 5 * i] = ((1 << j) & v1) == 1 << j;
} For-loops are easier to read than while- or do-loops. The decompiler prefers to generate for loops now. Again, note the difference in size and readability!

Better recognition of 64-bit idioms
v9 = v21 + v23; v23 += v21; *((_DWORD *)&v10 + 1) = *((_DWORD *)&v23 + 1); *(_DWORD *)&v10 = v9; *(_DWORD *)&v11 = GetShortField(v10, (int)"IMAGE_DEBUG_DIRECTORY", 1); if ( v11 ) break; v21 += v22; *(_DWORD *)&v8 = GetShortField(v21, (int)"IMAGE_DEBUG_DIRECTORY", 1); if ( v8 ) break; While we still do not recognize all 64-bit idioms (perfections is out of question in binary analysis) we do much better now. Above is just one of many possible examples (v10 on the left and v21 on the right are 64-bit variables),

Better recognition of 64-bit idioms, example 2
v21 = PageSize * (_DWORD)a6 - a2; v22 = __MKCADD__(v21, qword_6992C7E0); *(_DWORD *)&qword_6992C7E0 = v21 + qword_6992C7E0; *((_DWORD *)&qword_6992C7E0 + 1) += ((unsigned __int64)PageSize * a6 >> 32) - ((unsigned int)(PageSize * (_DWORD)a6 < (_DWORD)a2) + *((_DWORD *)&a2 + 1)) + v22; qword_6992C7E0 += PageSize * a6 - a2; Yet one more illustration of 64-bit arithmetics.

Floating point instructions
bool __cdecl ld_ull_cmpge(long double a1, __int64 a2) { __int64 v10; // @1 *(_DWORD *)&v10 = a2; *((_DWORD *)&v10 + 1) = *((_DWORD *)&a2 + 1) + -2147483648; __asm { fild fadd ds:dbl_10B74 fld fcompp fnstsw ax sahf
} return !_CF;
} bool __cdecl ld_ull_cmpge(long double a1, unsigned __int64 a2) { return a1 >= (long double)a2;
} One could say that this comparison is not fair and we would agree. Previous versions of the decompiler could not handle floating point instruction at all, and the new version knows all about them, including conversion intricacies and other subtle details.

Better recognition of built-in functions
v112 = v70 - 1; memcpy(v112, v71, 4 * (v68 >> 2)); v113 = v118 + 4; memcpy((char *)v112 + 4 * (v68 >> 2), (char *)v71 + 4 * (v68 >> 2), v68 & 3); v114 = *(_DWORD *)v113; v118 = v113; argc = v113; memcpy(v99 - 1, v100, v96); v109 += 4; v111 = (const char **)v109; While there is a lot to do, the new version copes better with inline memcpy(), strlen(), and similar functions.

More aggressive value propagation
signed __int64 __cdecl smodushort(signed __int64 a1, unsigned __int16 a2) { int v3; // @1 int v4; // @1 v3 = a2; v4 = 0; return a1 % *(_QWORD *)&v3;
} signed __int64 __cdecl smodushort(signed __int64 a1, unsigned __int16 a2) { return a1 % a2;
} Thanks to the more aggressive propagation algorithm, the output becomes simpler.

New algorithm to detect function arguments
result = sub_100270F(0); if ( result ) { v1 = sub_15F0000(); result = sub_100270F(0); if ( result ) { dword_100A480 = sub_15F0000(byte_1009628, -2147483648, 3, 0, 3, 128, 0); We switched to a new heuristic algorithm to detect arguments of unknown function calls. While it is not perfect, it loses less arguments and tends to produce more reliable output. Please note that this algorithm is required to determine the types of only unknown calls: once the user specifies the function prototype, it will be used by the decompiler.

Implicit value propagation
result = sub_402EE0(); if ( !result ) { v10 &= result; v6 = v3->pchar4; if ( v3->dword0 <= (unsigned int)result ) result = sub_402EE0(v3); if ( !result ) { v10 = 0; v7 = v3->pchar4; if ( v3->dword0 <= 0u ) The new decompiler can use comparison instructions (and other clues) to determine possible variable values. In the example above, it is clear that the result variable is equal to zero within the if-block. This knowledge allows for more optimizations and makes the code more readable.
页: [1]
查看完整版本: Hex-Rays v1.1 have been released