Latest available version: IDA and decompilers v8.4.240527sp2 see all releases
Hex-Rays logo State-of-the-art binary code analysis tools
email icon


Free updates can be requested directly from IDA, from:

Help > Check for free update...

Please use this page to request the new version of IDA and/or decompiler or to redownload the current version.


  • + added MAX_FUNCSIZE option to limit the input function size; the default value is 64KB
  • + added support for “call gs:10” linux32 syscalls
  • + added vds8 sample to demonstrate usage of udc_filter_t class (generate custom call instructions)
  • + arm: handle instructions FTOUIZD, FTOUIZS, translate FTOSIZD, FTOSIZS into m_f2i, FTOSID, FTOSIS into calls lrint, lrintf
  • + basic support for thread local variables in some situations
  • + decompiler tries to replace all fs/gs based memory accesses with intrinsic calls (for windows)
  • + decompiler version is now in sync with IDA’s
  • + improve varargs recognition
  • + improved conversion of if comparison chains into a switch statement
  • + improved inlined strcpy recognition
  • + improved recognition of .got based address calculations
  • + improved recognition of abs() and div/mod of power2
  • + improved the decompiler to handle array references with mismatching access size. for example, if we read only a byte of a word array. we now use a nice index expression like arr[idx]
  • + pressing Enter at the end of a line adds an empty line after it (since it is not possible to add empty lines everywhere, sometimes it is added to somewhere else or not added at all)
  • + remove identical if branches
  • + generate memcpy when handling strcpy33 rule in case a string is copied without terminating zero
  • + improved inlined memcpy recognition
  • + slightly improved recognition of variadic function types
  • + the user can jump to a lvar by double clicking on it when the debugger is suspended
  • + the current ea_t is printed as part of the current location information (in the statusbar)
  • BUGFIX: could hang (loop endlessly) a builtin function matching was failing at the very end
  • BUGFIX: “reset all local function info” was broken
  • BUGFIX: a pair of push/pop instructions could be annihilated even if there was a direct access (e.g. via ‘mov [sp], …’ instruction) to the corresponding stack slot
  • BUGFIX: a truncating cast of argument of abs() could be erroneously deleted
  • BUGFIX: arm: incorrect translation of instructions sxtb, sxth, sxtab, sxtah, sxtw, uxtw, uxtb, uxth, uxtab, uxtah (wrong operand size)
  • BUGFIX: changing of a global variable type did not initiate re-decompilation of some functions depending on the type
  • BUGFIX: combining low/high ldx instructions could lead to wrong microcode in some cases for big endian processors
  • BUGFIX: could display &data instead of plain integer in some cases
  • BUGFIX: division by zero could be erroneously produced in some cases
  • BUGFIX: fixed incorrect printing of low part of 128bit value when high part is not zero
  • BUGFIX: fixed many interrs (fortunately all of them occur very rarely)
  • BUGFIX: hexppc: fixed the decoding of the se_btsti (VLE) insn
  • BUGFIX: in 64-bit mode, all segment registers except fs/gs always map to zero
  • BUGFIX: in some cases 64bit addition rule could produce incorrect results
  • BUGFIX: in some cases 64bit multiplication by 2 could be transformed into incorrect expression
  • BUGFIX: in some cases combining rule for 64bit addition could produce incorrect results
  • BUGFIX: in some cases decompiler could produce pointer subtract expressions with swapped operands (y-x instead of x-y)
  • BUGFIX: in some cases magic ‘mod’ operation could be recognized incorrectly (truncated constant divisor)
  • BUGFIX: in some cases x86 FPU registers could be handled incorrectly
  • BUGFIX: necessary casts to int128 would be missing from the output
  • BUGFIX: patching a function byte would not mark the function as requiring a new decompilation output
  • BUGFIX: ppc: ‘bclrl’ used for indirect calls would not be decompiled
  • BUGFIX: removed incorrect optimization rule (low == 0 || high == 0) –> (full == 0)
  • BUGFIX: some registers were incorrectly translated into scattered arglocs on Big Endian platforms
  • BUGFIX: swapped arguments for intrinsic ‘atan2’, fixed target for intrinsics ‘__FPREM__’, ‘__FPREM1__’
  • BUGFIX: the conversion of the floating constant from the bits should ignore the endianness, it was accounted already
  • BUGFIX: try sign-extended value if zero-extended value does not correspond to any enum member but the user asked to use the enum
  • BUGFIX: use/def chains could not calculated incorrectly in some rare cases
  • PowerPC decompiler has arrived! It can handle 32-bit big endian code. See its limitations.
  • added proper support for big endian processors
  • added decompile as call to convert any instruction into a function call
  • ARM32: recognize MSVC intrinsic functions KeGetPcr, NtCurrentTeb
  • ARM32: added support vfp/neon registers
  • improved syscall handling for Linux and OSX
  • improved the rule “~x >> 31” => “x >= 0” to handle more cases
  • when converting case values to enum, use the case value to filter out possible the enum types
  • whether or not ‘Esc’ closes a “Pseudocode-” view when no more items are present in the history, is now configurable
  • BUGFIX: “decompile all” would skip non-trivial functions with tail chunks if the main chunk consisted of only one instruction
  • BUGFIX: clicking on some badly-broken types in the decompilation view could cause IDA to crash on endless recursion
  • BUGFIX: fixed many-many interrs (fortunately they do not happen often)
  • BUGFIX: fixed interr 50764 which could occur because of zmm registers
  • BUGFIX: functions with foreign tails could not be decompiled
  • BUGFIX: navigating over some addresses in ARM decompilation could cause hexrays to jump to another function
  • BUGFIX: pc: incorrect condition flags when translating instructions cmpxchg into intrinsic function calls
  • BUGFIX: some shift/and combinations would be erroneously optimized away
  • BUGFIX: some user-specified number formats would be ignored if there was a reference to a wrong enum or struct
  • BUGFIX: fixed a bunch or crashes and interrs (there are too many of them to list here)
  • ARM64 decompiler has arrived!
  • added MAX_NCOMMAS to limit the number of comma operators in expressions
  • added a new rule: (~x >> 31) == 0 => x <= 0
  • added a rule: fpval ^ 0x8000… => -fpval
  • added an action to revert CONTAINING_RECORD macro (if the macro was created from the pseudocode view)
  • added new rule: x + (-N) => x – N
  • added option “Print casts from string literals to pointers”
  • added support for _byteswap_uint64()
  • added support for andn and bextr instructions
  • added support for runtime data loss checking functions like RTC_Check_..
  • added support for smulbb and similar instructions
  • arm: added support for smfx
  • arm: big mixed scattered arguments were handled incorrectly
  • arm: renamed __rev and _revsh as bswapXX
  • better handling of movlpd/movhpd instructions (use regular mov’s instead of intrinsic calls)
  • better handling of user-specified variables that overlap with other variables; now we detect this situation and remove overlapping vars (for stkvars)
  • display the switch cases in sorted order (as signed numbers)
  • fix the current compiler or calling convention if they were not set
  • if only low part of an xmm intrinsic result is used, replace it with a regular operator (add/sub/mul/div/etc)
  • improved “unmerge_calls” to handle more cases
  • improved array handling: instead of p->array+p->idx now we output &p->array[p->idx]
  • improved array references. was &arr[i1]+i2. now: &arr[i1+i2]
  • improved detection of get_pc_thunk_xx functions
  • improved handling of clz(x)>>5
  • improved handling of sse2 floating point operations
  • improved handling of struct.field0 expressions in assignments
  • improved recognition of 64-bit multiplications
  • improved recognition of __thiscall calling convention
  • improved recognition of interblock setnz
  • improved recognition of sdiv/2
  • improved recognition of signed modulo by a power of 2
  • more accurate handling of va_list variables
  • more aggressive creation of return statements. this reduces number of gotos and leads to shorter output
  • pc: added support for the ‘std’ instruction
  • sdk: added api functions to create new map instances
  • simplified index expressions like ‘ptr[1-1]’ to ‘ptr’
  • BUGFIX: (&charptr)[idx] was incorrectly displayed as (&charptr)[idx*4]
  • BUGFIX: 16-byte assignments would be split into 4-byte assignments because we did not have support for 8-byte splits. added support for them
  • BUGFIX: 64-bit addresses could be truncated to 32-bits in the output
  • BUGFIX: aliased variables in the shadow argument area could be erroneously optimized away
  • BUGFIX: cast-8 rule could cause an internal error
  • BUGFIX: comparison of a floating point value against zero was decompiled incorrectly in some cases
  • BUGFIX: conditions codes after interlocked add/sub operations were not properly set
  • BUGFIX: decompiler was still refusing to use a bad type after fixing it because its cache of bad types was not flushed
  • BUGFIX: decompiler would now allow setting argument type in function prototype, when function was returning a deleted type
  • BUGFIX: deleting mmx types (line __m128i) after decompiling some functions that use them could lead to interr 50078
  • BUGFIX: fisttp instruction was not supported (it is usually not used by compilers; fistp is used)
  • BUGFIX: fixed interr 50192
  • BUGFIX: fixed interr 50318 which could occur if va_list was undefined or defined incorrectly
  • BUGFIX: fixed interr 50593
  • BUGFIX: fixed interr 50632
  • BUGFIX: fixed interr 50877 (incorrect handling of ARM instruction LDRD R0, R1, [R0,#8])
  • BUGFIX: fixed interr 51031 (however still we cannot handle scattered arguments well in some cases)
  • BUGFIX: fixed interr 51166
  • BUGFIX: if the source structure fields are calculated between assignment to the destination then put structure copy operator after all assignments
  • BUGFIX: in theory decompiler could lose some memory writes when optimizing microcode
  • BUGFIX: it was impossible to specify va_list as the function return type on x64
  • BUGFIX: local variable allocation could use wrong variables in some cases
  • BUGFIX: movddup instruction could cause interr 50098 in some rare cases
  • BUGFIX: propagating a call into stx could remove a sequence point
  • BUGFIX: psraw and similar instructions with an immediate second operand were decompiled incorrectly
  • BUGFIX: push/pop pairs with mismatching sp values would be incorrectly converted into mov
  • BUGFIX: some constant assignments could be missing from the decompilation output
  • BUGFIX: some floating point jumps were wrongly optimized away
  • BUGFIX: some interlocked intrinsic functions would not be recognized
  • BUGFIX: some references to imported symbols in relocatable elf files was handled incorrectly
  • BUGFIX: some references using CONTAINING_RECORD were wrong
  • BUGFIX: the decompiler would remove information about the variables used in an inlined function because they would disappear after collapsing the function; this would render future recognitions impossible
  • BUGFIX: in some cases decompiler rejected correct function prototypes entered by user (arm)
  • + improved the type derivation algorithms; now the decompiler assigns more non-trivial types to variables and functions and produces less cast operators
  • + added one more variant of the “== 0” interblock construct
  • + added support for functions that return scattered values
  • + better optimization of comparison operators
  • + improved the decompiler to replace references to __objc_ivar by constant values; this leads to much more readable output
  • + arm: added support for ‘orn’
  • + pc: added support for bsr/bsf
  • BUGFIX: could interr if a enum type was used in the decompilation and later rendered bad
  • BUGFIX: decompiler could consider registers used in scattered args as unused and add them to the function prototype once more
  • BUGFIX: decompiler could crash trying to unpack scattered args
  • BUGFIX: decompiler could hang if a switch case was a trivial multiblock endless loop
  • BUGFIX: decompiler could hang on some inputs
  • BUGFIX: decompiler could interr after displaying a warning message in some rare cases
  • BUGFIX: decompiler could interr if ‘explicit rip addressing’ was enabled
  • BUGFIX: decompiler sample plugin #2 had a bug in processing expressions like “ptr=0”
  • BUGFIX: editing the segment permissions will not have immediate effect on the decompilation results (reopening the database would be required)
  • BUGFIX: fixed many interr occurrences (50201, 50318, 50683, 50708, 50836, 50838, 50877, 50962, 50978, 51053, 51150)
  • BUGFIX: function types were not verified for overlapping scattered arguments, this could lead to an interr
  • BUGFIX: nested switches were decompiled incorrectly if the default case was jumping out of the switch
  • BUGFIX: removed interr 51171
  • BUGFIX: representation of some constants could not be specified by the user (some of them may still be unmodifiable due to inherent limitations)
  • BUGFIX: some ‘return’ statements were displayed as ‘JUMPOUT(__CS__, vXX)’
  • BUGFIX: some switch idioms were not decompiled correctly
  • BUGFIX: union field selection (Alt-Y) would fail on expressions like (char *)&union.field + N
  • BUGFIX: virtual tables of classes with multiple inheritance were printed without mentioning the base class
  • BUGFIX: wrongly guessed prototype of memset() could lead to interr 50502
  • BUGFIX: some actions could be enabled even though they didn’t make sense in their current context (e.g., ‘hx:BitwiseNegate’, …)
  • BUGFIX: arm: references to some global variables were not recognized

Many bugfixes and minor but yet useful improvements

  • + arm linux: convert EABI(svc 0) and OABI(0x9xxxx) to linux_eabi_syscall() and linux_syscall() function calls
  • + arm mac: rename SVC80 function syscall->mac_syscall
  • + added “.rodata” segment name to the list of read-only segments
  • + added recognition of == 0 and != 0 interblock constructs
  • + added some 64-bit patterns (memcpy, memset, strlen, strcpy etc.)
  • + added transformation rule (x = expr; return (TYPE)x) –> return (TYPE)expr
  • + minor improvement of microcode verification
  • + round size of scattered part to power of 2 when convert scattered vdloc to idaloc
  • + try to convert _bittest… functions to plain microcode
  • + use curly braces when the condition of if/for is multiline
  • + ARM: check for immediate loads which afftect carry flag (e.g. MOVS R1, #0x80000000) and set the CF accordingly
  • + value of WCHAR[] is printed as a unicode string, if possible (before we were doing so only for wchar_t)
  • + added a rule to combine preincrement operators with the next statement
  • + added support for 64-bit bit-related intrinsics
  • + better cast removal
  • + better handling of references to the first struct member (less casts and nicer expressions)
  • + improved transformation rules in order to make the output more readable
  • + improved recognition of 64bit comparisons agains a constant (arm)
  • + improved the control structure of the output in some cases
  • + improved the final transformation speed
  • + improved the rule to apply sizeof expressions instead of constants
  • + string literals are printed on multiple lines if necessary
  • + X64: support __readeflags() and __writeeflags() intrinsics
  • BUGFIX: arm: the SBCS instruction was decompiled incorrectly (condition codes were set wrongly)
  • BUGFIX: changing type of the very first stack variable in the decompiler did not change the type in the stack frame structure in IDA
  • BUGFIX: decompiler could create too many variables for unaligned stkargs instead of creating just one
  • BUGFIX: decompiler could interr trying to handle input arguments located in YMM registers
  • BUGFIX: decompiler could move postincrement operators into calls too aggressively
  • BUGFIX: decompiler would blindly trust offset expressions in the disassembly and produce wrong output
  • BUGFIX: fixed interr 1054
  • BUGFIX: decompiler view could scroll uncomfortably when toggling with <Tab>
  • BUGFIX: jumping to occurences of local variables through the xrefs window was not working
  • BUGFIX: pressing F5 while staying in the IDA View could lead to the wrong function’s decompilation to be displayed
  • BUGFIX: could crash if recompilation of the same function was recursively required
  • BUGFIX: entering extremely long comments could leave the IDB in a state decompiler could not handle, and cause INTERR 518
  • BUGFIX: pressing <Tab;> from the “Structures” or “Enums” view should bring focus back to the pseudocode view
  • BUGFIX: when changing a variable type in the decompilation view, ‘Structures’ xrefs might not be updated
  • BUGFIX: rdmsr() and similar functions were decompiled incorrectly in x64 mode
  • BUGFIX: “lss esi,…” would cause an interr (x64)
  • BUGFIX: a function that returns a struct with padding could lead to interr
  • BUGFIX: a tail call to noreturn function could case interr in some rare cases
  • BUGFIX: common type of 128 and 64 bit expressions was calculated incorrectly
  • BUGFIX: could interr on some fragmented functions
  • BUGFIX: could interr trying to recognize a memcpy call with odd arguments
  • BUGFIX: could interr while trying to generate readfsqword() intrinsic call
  • BUGFIX: decompiler could die because of stack overflow due to a too complex expression it created
  • BUGFIX: ‘extrq’ with immediate operands would lead to interr
  • BUGFIX: fixed a crash (rare)
  • BUGFIX: fixed interr 50007
  • BUGFIX: fixed interr 50183. huge structs with negative deltas would cause a multiplication overflow
  • BUGFIX: fixed interr 50212
  • BUGFIX: fixed interr 50213
  • BUGFIX: fixed interr 50513
  • BUGFIX: fixed interr 50312
  • BUGFIX: fixed interr 50336
  • BUGFIX: fixed interr 50360
  • BUGFIX: fixed interr 50356
  • BUGFIX: fixed interr 50360
  • BUGFIX: fixed interr 50377
  • BUGFIX: fixed interr 50445
  • BUGFIX: fixed interr 50708 (the consequence of introducing __m256X)
  • BUGFIX: fixed interr 50824
  • BUGFIX: fixed interr 50836
  • BUGFIX: fixed interr 50856
  • BUGFIX: fixed interr 50978 if an enum constant was used in left shift operation
  • BUGFIX: fixed interr 51053 (decompiler could modify an existing stkarg to start at an unaligned address and later fail because of that)
  • BUGFIX: fixed interr 51118
  • BUGFIX: fixed interr 51156
  • BUGFIX: fixed interr 51217 (could occur when there are some fixed register args but all registers are saved in prolog)
  • BUGFIX: fixed interr with scattered lvars
  • BUGFIX: fixed lvar allocation interr
  • BUGFIX: functions with too huge stack could cause an interr
  • BUGFIX: if a function had a pushf/popf pair as the last instructions (but no return), the decompiler would interr
  • BUGFIX: in some cases declaration of va_list variable could be lost
  • BUGFIX: in some cases the ‘select union field’ command was not available
  • BUGFIX: lsl insn could cause interr (x64)
  • BUGFIX: references to YMM registers in 32-bit programs could cause an interr
  • BUGFIX: transformation rule #22 could interr
  • BUGFIX: some scattered variables could lead to an interr
  • BUGFIX: some volatile accesses could still be propagated (volatile accesses may not be propagated at all)
  • BUGFIX: the transformation rule #43 to recognize multiplications could interr
  • BUGFIX: uninitialized values in the shadow stack area could cause an interr
  • BUGFIX: wrong variadic function type could lead to an interr
  • BUGFIX: wrongly defined basic blocks (with function chunks crossing the blocks) would cause an interr
  • BUGFIX: wrongly detected math function could lead to interr
  • BUGFIX: far memory model could cause interr 50977 in the arm decompiler
2014/06/04 The x64 decompiler has arrived! Other decompilers have been improved too, please see below:

  • + ‘volatile’ keyword can be used to override constness of an individual item
  • + introduced is_mul_ok() helper function to detect overflows in multiplications
  • + introduced qmemcpy() which always copies byte by byte, from the bottom to the top
  • + added recognition of an inlined bswap function
  • + double clicking on a label jumps to it
  • + the decompiler may use __spoils keyword to specify registers that are not spoiled by the function
  • + improved recognition of register save/restore patterns
  • BUGFIX: hexrays: “add pseudocode comments” was broken
  • BUGFIX: hexrays: an indirect call to a noret function in the middle of a function was not supported
  • BUGFIX: hexrays: arm decompiler could miss some return instructions and represent them as JUMPOUTs
  • BUGFIX: hexrays: big endian decompilation had constant halves swapped
  • BUGFIX: hexrays: decompiler could erroneously optimize away some expressions like ‘x*N & M’ and replace them with zero
  • BUGFIX: hexrays: decompiler could interr if 32-byte enum type was defined (too wide)
  • BUGFIX: hexrays: decompiler could interr on a comma operator whose type is a bitfield
  • BUGFIX: hexrays: decompiler could interr on some variadic functions
  • BUGFIX: hexrays: decompiler was always moving register arguments to the beginning of the argument list in the pseudocode window
  • BUGFIX: hexrays: def-list for strcat() was sometimes calculated incorrectly
  • BUGFIX: hexrays: enabled negation of 128-bit values, apparently they can occur even in 32-bit programs
  • BUGFIX: hexrays: expression like “(x * N) < 0” could be optimized wrongly in some rare cases
  • BUGFIX: hexrays: fixed a couple of minor memory leaks
  • BUGFIX: hexrays: fixed interr 50375
  • BUGFIX: hexrays: fixed interr 50396
  • BUGFIX: hexrays: fixed interr 50708
  • BUGFIX: hexrays: fixed interr 50860
  • BUGFIX: hexrays: fixed interr 51049
  • BUGFIX: hexrays: hexrays: the rule to recognize signed modulo by power2 could interr
  • BUGFIX: hexrays: hints for union members were wrong (off=N; where N is the member number, not the offset)
  • BUGFIX: hexrays: if the return value of a function call was used but could not influence the logic of the program, the call could be optimized out, which is wrong
  • BUGFIX: hexrays: movd/movq insructions with a register destination were decompiled incorrectly
  • BUGFIX: hexrays: recursive patterns could be applied wrongly and lead to an interr
  • BUGFIX: hexrays: ScreenEA() would sometimes return BADADDR in the decompiler view because some pseudocode locations cannot be mapped to an address. Now it tries to return the closest EA, or the function’s EA in the worst case.

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

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 “cannot 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)

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

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;
              if ( !count )
              zf6 = *esi4 == *(_DWORD *)edi3;
              edi3 += 4;
            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 (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

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


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


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.


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

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.


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.


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


  • + 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 )


  • 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

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.


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


  • + 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 cannot 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 *)


  • 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

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

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;
          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;
    byte_10098A1[result] |= 0x10u;
  • Better local variable allocation. Before:
    if ( result->f0 f0;
      this = (char *)this + 12;
      result->f0 = (_WORD)this;
    if ( result->f0 > 12 )
      LOWORD(this) = result->f0;
      result->f0 = (unsigned int)((char *)this - 12);
    if ( result->f0 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 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

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

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

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 cannot 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 cannot 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
  • + 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
  • + 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(
  • + multiplications by big powers of 2 are replaced by shifts
    v12 = 256 * v9->x1 + 65536 * v9->x2 + 16777216 * v9->x3 + v9->x0;
    v12 = (v9->x1 x2 x3 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
      return v18;
      return v18;
  • bugfix: fixed a minor and rare memory leak (lvar_ref_t)
  • + 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