Updates

Free updates can be requested directly from IDA, from:

Help > Check for free update...

Page for manual requests is here.

The order forms can be downloaded here

Changelog

2013/12/13

The biggest news are internal: now the decompiler uses a new type system. This change was overdue since quite long time: the old system was too limited and lacking expressive power. It was also difficult to use. Since the decompiler heavily relies on type information and we switched to the new type system, it can not be used with older versions of IDA anymore: decompiler v1.9 requires IDA v6.5. Unfortunately the x64 decompiler is not ready yet.

The decompiler has new algorithms to track the variable values and generates better output in general.

  • + the decompiler tries to keep indirect memory reads in the output even if the read result is not used; this usually leads to better output
  • + 'create new struct' command can be applied to global variables and structure members
  • + 'create new struct' command is also available for void* variables
  • + added support for "lock add" as InterlockedAdd() and "lock sub" as InterlockedSub() (and inc/dec too)
  • + added support for anonymous udt members in the CONTAINING_RECORD macro
  • + convert bitwise operations on boolean values to logical expressions (this is common in unoptimized GCC code)
  • + decompiler more aggressively reuses stkvar types for local variables
  • + improved recognition of while-loops that were converted to if-do-while by the compiler
  • + mark NaN and Inf floating point values in the listing
  • + minor improvement of add64 recognition
  • + some constants that were not present in the disassembly listing but created by the decompiler now can be represented differently by the user (as a symbolic constant, for example)
  • + ask the user to retry if failed to send the database
  • + ARM: added recognition of the get_current() macro
  • + ARM: improve recognition of 64-bit comparisons
  • BUGFIX: once decompiler failed, reopening the database was required to try decompilation once more (in some cases)
  • BUGFIX: ARM decompiler could crash on really long variable type declarations
  • BUGFIX: ARM: should not optimize memory across dmb/dsb/isb instructions
  • BUGFIX: cdq instruction was decompiled incorrectly
  • BUGFIX: collapsing a 64-bit comparison could produce wrong decompilation in some rare cases
  • BUGFIX: decompiler could fail to recognize standard functions because of a leading dot in the name
  • BUGFIX: decompiler could hang in some very rare cases
  • BUGFIX: decompiler could interr if during refreshing the pseudocode a decompilation problem occurred (interr 50464)
  • BUGFIX: decompiler could optimize away writes to the return address and saved registers on the stack frame
  • BUGFIX: decompiler was combining references to struct fields too aggressively
  • BUGFIX: definitions of ROL/ROR inline functions in defs.h were wrong
  • BUGFIX: entering wrong type info for a function argument could lead to interr
  • BUGFIX: expressions with arrays of pointers to a struct could be represented wrongly
  • BUGFIX: fcmovCC instructions were not decompiled
  • BUGFIX: ida could too aggressively create 64-bit comparisons
  • BUGFIX: in some rare cases lvar allocation could fail on LDM/STM instructions
  • BUGFIX: indentation of one-line 'else if' statements was calculated incorrectly
  • BUGFIX: initialization of some stack variables could be erroneously optimized away if they were used only indirectly
  • BUGFIX: IsListEmpty() was recognized but its result was sometimes negated
  • BUGFIX: it was impossible to delete name of a stkvar from the pseudocode window
  • BUGFIX: microcode for the OF flag generated by mul instruction was incorrect: it was using the value of DL instead of EDX
  • BUGFIX: names of stack variables were not always used in the output
  • BUGFIX: references to the first element of a structure type could be displayed as an ugly expression in some cases (for example: this[-1].array[idx+N] instead of this->array[idx-M])
  • BUGFIX: some accesses to volatile memory could be optimized away
  • BUGFIX: some enums could not be applied to narrow numbers
  • BUGFIX: some local variables were assigned a name from a wrong stack slot
  • BUGFIX: some sequences of xor and or operations could be wrongly replaced with a 64-bit comparison
  • BUGFIX: strings with custom encodings could be displayed truncated in the decompiler
  • BUGFIX: the 'const' or 'volatile' could hinder recovery of struct field accesses
  • BUGFIX: the decompiler was automatically sending IDBs to Hex-Rays on interrs if invoked from a plugin in batch mode
  • BUGFIX: the decompiler was not always refreshing the pseudocode window after changing the type of a function argument
  • BUGFIX: the mul64 recognition rule16 could remove some memory references and produce wrong output
  • BUGFIX: the pcmpistri instruction could cause an interr
  • BUGFIX: the remove-useless-mov rule was wrong and quite useless itself; threw it away
  • BUGFIX: the return value in xmm0 could be incorrectly ignored in some cases
  • BUGFIX: the rule to combine bitwise AND instructions into 64-bit was wrong
  • BUGFIX: variable allocation could fail in the presence of some bit test/clear/set instructions
  • BUGFIX: when opening more than 26 pseudocode views, non-ascii characters could appear in the window title
  • BUGFIX: while source debugging, the decompiler would position the cursor on do-statement lines. this is incorrect because do-statement lines do not corresponds to any code
  • BUGFIX: fixed interr 50194
  • BUGFIX: fixed interr 50340
  • BUGFIX: fixed interr 50355
  • BUGFIX: fixed interr 50725
  • BUGFIX: fixed interr 50782
  • BUGFIX: fixed interr 50831
  • BUGFIX: fixed interr 50838
  • BUGFIX: fixed interr 50894
  • BUGFIX: fixed interr 50902
  • BUGFIX: fixed interr 50920
2013/03/06 This is a bugfix release, fixing various minor issues in the original 1.8 release.

  • BUGFIX: ARM: functions with epilog of form LDMDB R11, {R11,SP,PC} were not decompiled properly
  • BUGFIX: ARM: vmov.f64 was decompiled incorrectly (it was overwriting the CS pseudoreg)
  • BUGFIX: decompiler could crash IDA when double-clicking outside of decompiled text
  • BUGFIX: decompiler could crash IDA with "Unknown C++ exception" while trying to show a hint for a bad/deleted type
  • BUGFIX: decompiler would crash IDA when trying to use variable mapping function on an assignment with a global variable
  • BUGFIX: fixed interr 50743
  • BUGFIX: SDK was not usable with GCC
  • BUGFIX: some enums could not be applied to narrow numbers
  • BUGFIX: when changing variable's type to a struct pointer via the context menu, an exception could escape to IDA if the type was invalid
2013/01/10 We continue to work on the x64 decompiler, so there are no major changes, but there are many minor improvements and fixes.

We will prepare a comparison page soon.

  • + ARM: handle Windows on ARM intrinsics that use UND opcode (__debugbreak, __fastfail, __brkdiv0 and others)
  • + ARM: better handling of MOVW/MOVT pairs
  • + decompiler tries to preserve the call argument addresses not only for constants but for other expressions too
  • + more aggressive conversion of x & 0xFF and similar expressions into casts like uchar(x)
  • + added recognition of RtlStoreUshort/RtlRetrieveUshort and similar macros; however, due to the optimizations these macros can not be always recognized
  • + local variable declarations can be hidden using the keypad - key
  • + nested if's are combined into a single if when possible
  • + new rule: "ok=x&&y" is transformed into if's if there are comma operators on the right side
  • + compiler helper functions like security_check_cookie and similar are ignored and do not appear in the output
  • + improved constant tracking
  • + add a config option to set the default raidx of constant values
  • + improved recognition of 'signed modulo power2'
  • + added a rule to remove cast from (type)x|N if N has its high bits set
  • + improved recognition of CONTAINING_RECORD
  • + added support for pure functions
  • + added support for __noreturn keyword in function prototypes
  • + recognize more variations of inlined strlen and strcpy functions
  • + print big pow2 and pow2-1 values in hex by default
  • + we distinguish booleans of different sizes and use bool, BOOL, _BOOL# types
  • + it is possible to jump to names and addresses in comments by double clicking
  • + added common subexpression elimination within basic blocks
  • BUGFIX: side effects of call expressions were not always taken into account
  • BUGFIX: setnz microinstruction with equal operands was being optimized incorrectly
  • BUGFIX: CAST-12 rule was too aggressive with signed casts, it was deleting them when they were important. for example:
  • BUGFIX: high_sub64 rule could generate wrong code
  • BUGFIX: parenthesis were missing around some division operations
  • BUGFIX: rule XDU26 could produce wrong result because it could combine instructions while it was unsafe to do so
  • BUGFIX: some calls could be completely eliminated from the output, which was wrong
  • BUGFIX: unsigned modulo operations could be reduced to lower bitness, which is wrong
  • BUGFIX: F1 should open the decompiler manual
  • BUGFIX: 'rename label' command would always rename the current label even if the user clicking on a goto target
  • BUGFIX: arm: code in with non-zero base could not be decompiled correctly (in general segments with non-zero base are not supported)
  • BUGFIX: arm: microcode for sbc was generated incorrectly in some cases
  • BUGFIX: CAST-4 rule could wring remove a cast operation
  • BUGFIX: changing the function end would not clear the cached decompilation results for it
  • BUGFIX: could crash if a previously decompilable functon with a source breakpoint becomes non-decompilable
  • BUGFIX: decompier was assigning 'bool' type to variables too aggressively; bool can be used only when the variable value is restricted to 0/1 values
  • BUGFIX: decompiler could crash in functions returning arrays
  • BUGFIX: decompiler was erroneously creating 64-bit comparisons while the binary code was not really comparing 64-bit values (rare)
  • BUGFIX: decompiler would wrongly consider some hex/oct numbers as signed
  • BUGFIX: fixed somehow unexpected crash at the exit time
  • BUGFIX: function prototype of a tail call was propagated to the caller too aggressively
  • BUGFIX: functions with wrong fpu stack could interr the decompiler
  • BUGFIX: in some cases Tab would decompile a wrong function
  • BUGFIX: it is possible to edit indented comments staying on any comment line (before only the first line was responsive)
  • BUGFIX: jnz64 could lead to wrong decompilation result
  • BUGFIX: optimization could replace a bitwise and with a shift right, thus producing ugly output
  • BUGFIX: rebasing a database with source breakpoints in the pseudocode window could lead to interr 40253
  • BUGFIX: representation of some constants was not modifiable by the user (please note that not all constants can be modified)
  • BUGFIX: SDK: cfuncptr_t object returned by decompile() could be destroyed at arbitrary time because of wrong reference count
  • BUGFIX: signed comparisons could be erroneously optimized away in some (rare) cases
  • BUGFIX: signed right shifts on constant operations were not performed correctly and could lead to wrong output
  • BUGFIX: some CONTAINING_RECORD macros were not used while they should have been
  • BUGFIX: some decompiler information would become stale after rebasing
  • BUGFIX: some ternary expressions like cnd ? N1 : N2 were produced incorrectly
  • BUGFIX: stack variable values were displayed incorrectly for some arm functions (when the frame pointer was reused for other purposes)
  • BUGFIX: stray { was still printed for collapsed blocks
  • BUGFIX: string constants with explicitly specified encoding were not displayed inline
  • BUGFIX: the low bound of indirectedly referenced stack variables was calculated wrongly; this could lead to wrong decompilation
  • BUGFIX: type of the negation operation was calculated incorrectly
  • BUGFIX: void pointers could be used in subtraction in the output; it is better to cast them to char*
  • BUGFIX: zero propagation was too aggressive and could produce wrong output
  • BUGFIX: numerous internal errorrs have been fixed
2012/05/31

The main news is support for source level debugging: it is possible to single step over the decompiler output, add breakpoints, check variable values, etc. While we expect many problems (after all, it is our first attempt to create a source level debugger), it is still very useful. Just to be on the safe side, let's call this feature 'experimental'.

Please refer to the comparison page to see concrete examples.

  • + added support for source level debugging
  • + implemented cache of decompiled functions; functions stay in the cache once decompiled; repeated decompilation requests use the cache, except forced refreshes (by pressing F5 in the pseudocode window)
  • + in conditions, prefer !strcmp(x, y) - this produces cleaner code when many strings are being tested in sequence
  • + print else-if on the same line, without extra indentation
  • + print data declarations in the batch mode output
  • + 'convert to struct*' can be applied to struct members too
  • + ui: added a command to jump to the structure definition for structure members (hotkey 'Z')
  • + ui: added a command to jump to the local type definition for user types
  • + added a rule to recognize if-then-else used to generate a boolean variable
  • + added support for "int 29h" (__fastfail on win8)
  • + added support for __readeflags() and __readcallerseflags() intrinsic functions
  • + added support for _aeabi_ulcmp/_aeabi_lcmp
  • + better handling of MOV/MOVT sequence generated by some arm compilers
  • + better handling of negative indexes into arrays of structures
  • + do not optimize away writes to volatile memory
  • + improved argument detection for ellipsis calls
  • + improved handling of function calls with known roles (like memmset, strcpy, etc)
  • + improved recognition of 64-bit != operator generated by gcc
  • + improved recognition of 64-bit inegality comparisions against zero
  • + improved recognition of ternary operators: (x-1) & y => x ? 0 : y
  • + recognize intrinsics involving CR and DR registers
  • + recognize more variations of _Interlocked(And|Or|Xor) intrinsics
  • + x86: recognize NtCurrentPeb() macro
  • + all jump commands (Ctrl-L, Ctrl-P, G, etc) work in the pseudocode window
  • + for CONTAINING_RECORD try to use the stroff delta stored in the idb
  • + added support for stroffs with deltas applied to zero offsets. now we create CONTAINING_RECORD for them too
  • + improved renaming functionality: name prompt doesn't close on error; it's possible to restore a dummy name by deleting name; offer to add suffix when a global name already exists
  • + when mapping a variable in an assignment, focus selection on another side of assignment
  • + comparison of enum members against zeros is represented nicely (not with a logical negation, as before)
  • + Ctrl-A can be used to select entire function text
  • BUGFIX: "push reg" was handled incorrectly if "reg" was a segment register
  • BUGFIX: 16-bit addtions/subtractions can be produced by the microcode optimizer but the verifier was rejecting them
  • BUGFIX: a pointer difference was wrongly assumed to have 'uint' type, it is 'int' (or ptrdiff_t)
  • BUGFIX: application of a byte enum to dword operand would lead to interr 50978
  • BUGFIX: ARM: LDREX, STREX and STRT instructions were converted to intrinsics incorrectly
  • BUGFIX: ARM: ldrh pc,... would cause an interr
  • BUGFIX: ARM: some LDM instructions with writeback were decoded incorrectly
  • BUGFIX: decompiler could erroneously remove code (usually assignments of zero constants)
  • BUGFIX: decompiler could interr trying to print the global type list with pointers to undefined types
  • BUGFIX: decompiler could interr if mm types were defined incorrectly; now it properly displays a compresenhible error message and decompiles the function without use of mm intrinsic functions
  • BUGFIX: decompiler did not handle properly indirect calls to no-return functions
  • BUGFIX: decompiler was destroying some essential sequence points (it could combine a call with an expression that uses the call result, like f(&x) + x)
  • BUGFIX: deleting a function should close the corresponding pseudocode window(s)
  • BUGFIX: fixed a crash in arm decompiler (when trying to decompile BLX SP)
  • BUGFIX: fixed one more corner case in lvar allocation
  • BUGFIX: forbid mapping of argument variables because it can lead to many problems
  • BUGFIX: global propagation could produce wrong results because of stale use-def chains
  • BUGFIX: if the result of a division was truncated using a cast, the cast could be erroneously optimized away
  • BUGFIX: if the user specified wrong type for the return variable, the decompiler could interr
  • BUGFIX: it should not be possible to map return registers to another variable because it can spoil the function prototype
  • BUGFIX: jecxz with the jump target to the next block was not handled correctly
  • BUGFIX: lvar allocation could wrongly create 2 distinct variables for the same location in some quite rare cases
  • BUGFIX: repe cmpsb was incorrectly decompiled as strncmp (should be memcmp)
  • BUGFIX: the decompiler could crash in some cases
  • BUGFIX: the function that replaces pairs on the right hand of assignments was wrong and could lead to wrong decompilation output
  • BUGFIX: the user was told that the database upload failed even if succeeded
  • BUGFIX: too complex structure types were truncated by the dialog box because of the fixee buffer size (4KB)
  • BUGFIX: union fields were not selectable in some cases
  • BUGFIX: variable allocation could produce wrong results in the presence of variables spoiled by function calls but not used
  • BUGFIX: ARM: some expressions involving RSB instructions were decompiled wrongly
  • BUGFIX: block combining step could erroneously remove some conditional jumps
  • BUGFIX: changing the stack change points was not invalidating the cached decompilation result; it should
  • BUGFIX: the decompiler could silently produce wrong output if some sections were marked as readonly but there were write accesses to them; added 'write access to readonly memory' warning; this warning is also displayed at the function header (in the
  • BUGFIX: sometimes decompiler could fail with "can not convert to microcode" if macro instructions were present
  • BUGFIX: fixed interr 50032
  • BUGFIX: fixed interr 50208
  • BUGFIX: fixed interr 50324 (tail calls could lead to lvar allocation failure)
  • BUGFIX: fixed interr 50384
  • BUGFIX: fixed interr 50504 (which could occur when an incorrect til was loaded)
  • BUGFIX: fixed interr 50513
  • BUGFIX: fixed interr 50669
  • BUGFIX: fixed interr 50708
  • BUGFIX: fixed interr 50732 (which was occurring when a wrong function prototype was specified by the user)
  • BUGFIX: fixed interr 50757
  • BUGFIX: fixed interr 50778
  • BUGFIX: fixed interr 50803
  • BUGFIX: fixed interr 50854
  • BUGFIX: fixed interr 50860
  • BUGFIX: fixed interr 50897 caused by incorrect user mapping (from a function argument) saved in the database
  • BUGFIX: fixed interr 50920 (many occurrences)
2011/10/05

The highlights of this release: better handling of combined calls, improved support for unions, structure copies are recognized nicely, added support for some Windows intrinsic functions. The output in some cases is much better than before. Please refer to the comparison page to see the improvements. Also, read our blog post for more information!

  • + structure copy operations are recognized
  • + better handling of complex conditions: less comma operators, clearer output
  • + un-merge combined calls
  • + added support for union field selection
  • + reduce number of gotos by undoing branch tail merging optimization
  • + convert to tail calls JMPOUTs caused by execution flow into another function
  • + any constant in the output can be converted into 'offsetof()' macro (analog of structure offsets)
  • + added intrinsic functions for fxsave/xsave and fxrstore/xrstore
  • + added recognition of _InterlockedAddLargeStatistic()
  • + added recognition of rep stosb (intrinsic memset)
  • + added recognition of repe cmpsb (intrinsic strncmp)
  • + added recognition of the NtCurrentTeb() inline function
  • + added recognization of some intrinsic functions that read from fs:
  • + added support for CONTAINING_RECORD macro. The user can force the decompiler to use it by specifying the structure offset and manually setting the variable types.
  • + added variable mapping: the 'map variable' command can be used to replace all occurrences of a variable by another variable
  • + CFString literals (common in OS X programs) are printed using the CFSTR() macro
  • + fields of union type starting with __ with an anonymous type are considered anonymous; their names are not printed in the output
  • + if the type derivation phase discovers new floating point variables, mark the corresponding statements as floating (use a floating assignment instead of an integer assignment, for example)
  • + improved detection of inlined memset()
  • + improved detection of short/char variables
  • + improved recognition of built-in string functions
  • + recognize inlined strcat()
  • + sgdt and lgdt are decompiled as intrinsics
  • BUGFIX: the order of mul/div/mod operations was not always preserved (some parentheses were missing)
  • BUGFIX: some Delphi functions were decompiled incorrectly ret-as-jumps were not decompiled as such
  • BUGFIX: string constants were cut off at a first non-printable character
  • BUGFIX: self-modifying code could cause the decompiler to delete the currently decompiled function
  • BUGFIX: functions using all 8 fpu registers could not be decompiled nicely
  • BUGFIX: arguments of borland fastcall functions with stack arguments were printed in wrong order in the function prototype
  • BUGFIX: 'force call' was failing if applied to call in an 'if' condition; unfortunately some comments attached to such if's will become orphan
  • BUGFIX: __ROL__ and __ROR__ templates could not handle properly negative shift counts
  • BUGFIX: __usercall functions that return a floating point value would cause an interr
  • BUGFIX: create_field_name() was crashing on array types
  • BUGFIX: decompiler could hang up when trying to print very long expressions
  • BUGFIX: decompiler could interr trying to recognize an inlined strlen()
  • BUGFIX: fixed an occurrence of interr 50691
  • BUGFIX: fixed interr 50838 which could happen with obfuscated code
  • BUGFIX: illegal instruction 'strd pc,...' would cause an interr
  • BUGFIX: incorrect types in the idb could lead to interr (rare)
  • BUGFIX: interr 50094 could occur if unusual order of registers was specified in a register pair argument (e.g. eax:edx instead of edx:eax)
  • BUGFIX: lvar allocation could interr for some promoted arguments (rare)
  • BUGFIX: the decompiler could not run on ida5.7
  • BUGFIX: when 'hide casts' option was turned on, some constants were printed with garbage at the end
  • BUGFIX: wrong function types in the idb could cause an interr
  • BUGFIX: wrong user-specified argument types could lead to interr
  • BUGFIX: xscale fpu instructions were causing an interr
2011/04/08

We continue to improve the decompilation engine to handle 64-bit arithmetics, to add more heuristic rules and, naturally, to fix bugs. Our first priority is to make the listing more readable.

  • + ARM: added support for SXTAB/SXTAH/UXTAB/UXTAH instructions
  • + ARM: added support for UBFX, BFC, BFI instructions
  • + added a rule to simplify expressions where two pointers of the same type are subtracted
    before: (signed int)((char *)pwsz1 - (char *)pwsz2) >> 1
    after:    pwsz1 - pwsz2
  • + some nested structure field references were not recognized (the output was correct but ugly)
    before: strlen(*(char **)(4 * n + v1 + 28));
            ST0C_4_2 = *(char **)(v2 + v1);
    after:  strlen(v1->wday[n]);
            ST0C_4_2 = v1->wday_abbr[v2];
  • + added option to convert signed comparisons of unsigned values against zero to bit operations
    before: (signed int)x < 0
    after:  (x & 0x80000000) != 0
  • + "repe cmpsd" is decompiled nicely
    before: esi4 = arg8;
            count = 4;
            zf6 = 1;
            do
            {
              if ( !count )
                break;
              zf6 = *esi4 == *(_DWORD *)edi3;
              ++esi4;
              edi3 += 4;
              --count;
            }
            while ( zf6 );
    after:  zf6 = memcmp(arg8, (const void *)edi3, 16) == 0;
  • + SDK: exported gather_derefs() and strtype_info_t
  • + SDK: exported comparison operators
  • + added rule: x << 31 < 0 => (x & 1) != 0
  • + added a rule to convert high(x << N) to low(x >> M)
  • + added a rule to detect sar64: (xh<<N)|(xl>>M) where N+M=32
  • + added a rule: or (x.4 >>l #M) | (#N*nsign(x.4))) => high(xds(x)*#N)
  • + added option to configure handling of string literals
  • + added support for yet another smod_power2 idiom
  • + added a rule to recognize 64-bit left shift
  • + improved a rule to recognize 64-bit multiplications (rarely used)
  • + improved add64 detection
  • + improved detection of 64bit function return values for the case when they are zero extended from a 32-bit value
  • + improved mul64 recognition
  • + improved recognition of 64-bit comparisons
  • + improved recognition of signed multiplication by a constant
  • + improved the heuristic rule to determine the function return type; it was failing on some functions returning short or char
  • + more aggressive conversion of integers to floating point values
  • + partial references using variables of "int64*" type are recognized and combined
  • + string variables are printed as literals only if they reside in read-only memory
  • BUGFIX: add64 (rule30) may produce wrong output
  • BUGFIX: arm: calls to imported helper functions were not recognized
  • BUGFIX: arm: STRT instruction was decompiled into an intrinsic function incorrectly
  • BUGFIX: bit manipulation instructions (btc/bts/bt/btr) with a register operand were not decompiled correctly
  • BUGFIX: decompiler could erroneously accept an inacceptable type for a local variable and interr after that
  • BUGFIX: decompiler was erroneously requiring sizeof(bool) to be 4 bytes
  • BUGFIX: decompiler was erroneously using partial types even if the operand sign was important; fixed this; now arm_divmul_cl_O1 file produces correct results
  • BUGFIX: decompiler would interr if a wrong function return type was specified by the user (for example, int in the st0 register)
  • BUGFIX: the dialog box for setting decompiler warnings was unnecessarily wide
  • BUGFIX: fixed a rare interr during save/restore analysis
  • BUGFIX: high22 rule was incorrect
  • BUGFIX: in some cases it was impossible to modify a function type from ida if a pseudocode window for it was open
  • BUGFIX: inverting sign of 2-word positive constants could hang the decompiler
  • BUGFIX: operand signness was not correct for partial types (_DWORD, etc); now we replace a partial type with a well defined type if the sign matters
  • BUGFIX: some forms of inlined strlen() were recognized incorrectly (the results were off by 1)
  • BUGFIX: some intrinsic functions (__pinsrw/__pld/__strex) were decompiled incorrectly
  • BUGFIX: some mov fs:... instructions were decompiled incorrectly
  • BUGFIX: some signed operations had operands of wrong signness
  • BUGFIX: the decompiler was interring after a failed lvar allocation (it should relax its internal checks in this case)
  • BUGFIX: the function body was always using indentation of 2, regardless of the config file setting
  • BUGFIX: transform_hilo() was not taking into account the sign of the parent operation; this would lead to output
  • BUGFIX: values of edi/esi registers could be erroneously destroyed before calling a usercall(esi/edi) function; the same problem existed with floating point registers
2010/10/01

The new v1.4 version of the decompiler works natively on Linux and Mac platforms. Unix fans do not need to run an MS Windows in a virtual machine to use the decompiler anymore. We continue to improve the decompiler in other aspects too, please check out the detailed changelist below:

  • + added support for enum bitmasks
  • + added support for volatile memory: references to such memory are not propagated
  • + :: and <> symbols are allowed in demangled names, this makes decompilation of c++ programs nicer (we still produce c code)
  • + added support for octal numbers
  • + improved handling of promoted to int arguments
  • + minor improvement of magic division detection
  • + ARM: improved optimization of "&global - delta" expressions
  • BUGFIX: arguments of some math oriented intrinsic visual studio functions were reversed
  • BUGFIX: ARM decompiler could interr on VMOV insn (in some rare cases)
  • BUGFIX: ARM: the decompiler was ignoring the carry flag that was set by shifted register operands
  • BUGFIX: decompiler could create a call to memset() while the block was filled by integer values, not bytes; introduced memset32() for that
  • BUGFIX: decompiler could destroy a user-defined stack array and replace it by an array of anonymous structures
  • BUGFIX: decompiler could endlessly display "illegal unk type size" in some rare cases
  • BUGFIX: decompiler could interr if a enum type name was reused for a structure type
  • BUGFIX: functions with deep pointer dereferences (more than 10 indirections) were decompiled very slowly
  • BUGFIX: IDA was exiting if decompiler could not create output file
  • BUGFIX: imported pointer variables in pe files were handled incorrectly
  • BUGFIX: it was possible to rename only the first variable of the multiple variables occupying the same stack slot
  • BUGFIX: some stkvar names were not copied to the pseudocode window; as the result, some variables could not be renamed
  • BUGFIX: structure offsets in disassembly view were ingored; now they are used to create sizeof() and offsetof() expressions
  • BUGFIX: the code to recognize magic divisions could produce "x/0"
  • BUGFIX: the decompiler could interr because of integer overflow during pointer correction
  • BUGFIX: the propagation algorithm could produce incorrect results in some rare and complex cases

2010/07/07

Just a small bugfix: it was impossible to edit indented comments.

2010/06/28

Welcome to the new v1.3 of our x86 and ARM decompilers! There are lots of changes, but it is difficult to sum them up with one or two words. Please refer to the comparison page to see the improvements.

One thing requires more explanations because it could not fit the comparison page, though. It is about the local variable allocation failures. Before there was not much to be done. Now the decompiler will still try to generate an output even if such a failure happens. Second, there are some corrective actions that can be taken to fix things.

NITPICKY DETAILS

  • + substrings of constant strings are printed nicely (before they were printed as &aName[idx])
  • + added 'Add/delete variadic argument' command: it adjusts the number of arguments of a variadic call
  • + added 'Force call type' command: it may be used to fix the call arguments for indirect calls
  • + added 'Extract function' command: it deletes all bytes from the database except belonging to the current function
  • + added support for function arguments on arbitrary register pairs (before only adjacent registers were supported)
  • + more aggressive detection of zero values
  • + improved rule to handle cmp-store-jump sequences: "if ( (var=*ptr++) == 0 ) ..." is decompiled nicely
  • + implemented global propagation of assertions
  • + implemented fast structural analysis: it works faster for huge functions. it also generates less number of nested if-statements (they are replaced by if ( cnd1 && cnd2 ... )) but may occasionally create unnecessary gotos
  • + global propagation was handling only registers; now it can handle non-aliased stkvars too
  • + index expressions are simplified: array[idx/8] is replaced by array[idx] if idx is divisible by 8 without changing the program semantics
  • + improved support for multilevel subscript expressions like array[i][j][k]
  • + improved recovery of complex expressions
  • + added rules to invert branches or remove useless branches
  • + added a rule: (x << n) >> n => sign_extend(x)
  • + better analysis of register arguments of calls
  • + added an option to ignore lvar allocation failures and generate an output; turned this option on by default
  • + hexrays options are saved in the idb and can be edited from the user interface
  • + renaming stkvars in ida renames them in the decompiler too
  • + decompiler displays formal argument names in call argument hints
  • + type hints for function calls include argument names
  • + SDK: added get_warning() to get information about decompilation warnings
The bug list is longer than usual but almost none of them were encountered by the users.
  • BUGFIX: __spoils keyword was never used in function declarations
  • BUGFIX: some calls were propagated too far and could lead to incorrect output
  • BUGFIX: shr(sar) could get combined into simple shr, which is wrong
  • BUGFIX: requesting an update without clicking OK to refresh the email was using the old email
  • BUGFIX: fixed a quite rare null pointer dereference (crash)
  • BUGFIX: the decompiler could set a function type to be a pointer to a function type in some rare cases
  • BUGFIX: the decompiler could not intialize itself if an instant windbg debugging session was active
  • BUGFIX: the decompiler could interr trying to handle (type *)(&ptr->foo.bar + constants...) in some cases
  • BUGFIX: clicking on ... of vararg functions could lead to a crash
  • BUGFIX: *(&x+N) was sometimes incorrectly transformed into &x->fieldN
  • BUGFIX: data flow analysis would incorrectly handle strcpy() calls with known source string length
  • BUGFIX: the rule to combine mov and mov with zero extension could spoil the output
  • BUGFIX: character constant '\'' was printed without backslash
  • BUGFIX: the memory visible to pc-intrinsic functions was calculated incorrectly
  • BUGFIX: cf/of flags of addition operators were presented wrongly in the output (usually they are optimized away but in some cases stay in the output)
  • BUGFIX: &strtable+idx was sometimes erroneously represented as (&strtable[0])[idx]
  • BUGFIX: incorrect user-defined local types would prevent decompilation instead of being automatically skipped
  • BUGFIX: rule35 to combine a comparison and a conditional jump was too aggressive and could yield wrong code
  • BUGFIX: pointers to ellipsis functions were detected correctly but were not stored into the idb, this would create problems later
  • BUGFIX: arguments of tail calls were incorrect in some cases
  • BUGFIX: 'copy to assembly' could crash on big functions
  • BUGFIX: the rule to combine bitwise operations could produce incorrect code
  • BUGFIX: zero/sign extended moves from memory to xmm registers were not decompiled correctly and could interr
  • BUGFIX: jump tables consisting of one entry could lead to interr
  • BUGFIX: cvtdq2pd/cvtps2pd/cvttps2pi/cvtps2pi with a memory operand could lead to interr
  • BUGFIX: string constants could be truncated if the corresponding string item in the database was too short
  • BUGFIX: the high(bnot) optimization rule could interr
  • BUGFIX: the decompiler would interr trying to use empty structure type definitions
  • BUGFIX: the decompiler could interr on some fragmeneted functions with fpu instructions because of miscalculated fpu stack (very rare)
  • BUGFIX: SSE shift instructions with immediate shift amount were decompiled incorrectly
  • BUGFIX: modifying a register argument of a function would not automaticallt modify the function prototype; it should
  • BUGFIX: the decompiler could corrupt memory if ida was working with a non-x86 processor
We also fix two bugs in the ARM decompiler:
  • BUGFIX: ARM: neg[s] rx, rx was decompiled incorrectly
  • BUGFIX: ARM: STMDB with writeback was decompiled incorrectly
2010/06/03

We are proud to present our ARM Decompiler v1.0!
This is the first release but it already supports real world code, including variadic functions, ARM and Thumb encodings, and can handle code for any ARM platform. Please refer to the comparison page for decompilation samples.

The ARM Decompiler requires IDA v5.7 or higher.

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

  • + added 'split' command to split too wide assignments
  • + added support for signed magic divisions
  • + all useless mov instructions are optimized away (before movs of aliased memory were preserved)
  • + better detection of function return types: floating point flags are assumed to be never returned by functions
  • + equivalent table jump instructions are collapsed into one instruction: this reduces the code complexity and speeds up the decompilation
  • + functions having no fpu insns but returning a fp value (for example, as the result of a call to another function) were not detected as fpval returning functions
  • + improved recognition of smod_power2
  • + improved the speed of decompilation
  • + objc_msgSend() and similar function prototypes are hardcoded into the decompiler to make the initial output better
  • + segments with predefined names (.rdata, __const, etc) and considered to be readonly and the decompiler replaces references to such segments with the constant values from them
  • + series of xchg/fxch instructions are handled better
  • + strcpy() inlined with series of mov's is recognized
  • + superfluous LOBYTE() and similar macros are removed, like in LOBYTE(x) & 1
  • + 'jump to xrefs' command supports structure fields, labels, statement types, local variables. For example, it is possible to get a list of all references to 'myvar':
    Type Line Col  Pseudocode line
    w    94     6  myvar = !(dwScanFlags & 1) &&
                          _this->m_dwStage != 1;
    r    95    14  var30 = myvar;
    r    96    11  if ( myvar )

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