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

In order to show the user only the most relevant code and hide the unnecessary clutter, the decompiler performs various optimizations before displaying the pseudocode. Some of these optimizations rely on various assumptions which are usually correct in well-behaved programs. However, in some situations they may be incorrect which may lead to wrong output, so you may need to know how to fix them.

Constant data and dead code removal

Consider this example from a recent iOS kernelcache:

The function looks non-trivial (I’ve had to zoom out the graph) but the pseudocode is very short. Most of the conditional branches visible in the graph have disappeared. What’s happening?

You may get some hints from the warnings shown by the decompiler when you first decompile the function:

[Information]
The decompiler assumes that the segment 'com.apple.kernel:__cstring' is read-only because of its NAME.
All data references to the segment will be replaced by constant values.
This may lead to drastic changes in the decompiler output.
If the segment is not read-only, please change the segment NAME.

In general, the decompiler checks the segment permissions, class, and name
to determine if it is read-only.

If you have checked “Don’t display message again” previously, the message will be shown in the Output window:

[autohidden] The decompiler assumes that the segment 'com.apple.kernel:__cstring' is read-only because of its NAME.
All data references to the segment will be replaced by constant values.
This may lead to drastic changes in the decompiler output.
If the segment is not read-only, please change the segment NAME.

In general, the decompiler checks the segment permissions, class, and name
to determine if it is read-only.
 -> OK
FFFFFFF007E6ABAC: conditional instruction was optimized away because cf.1==1

The last message is also a useful hint: if you double-click the address you’ll land on the instruction which was “optimized away”.

If we double-click the variables involved in the condition, we can see that they both are situated in the segment mentioned in the warning message (com.apple.kernel:__const):

So, apparently, because the segment is considered read-only and both variables are set to zero, the decompiler deduced that the branch is always taken and removed the check itself as dead code. Similarly it removed many of the previous comparisons. But is this assumption correct?

Not very constant

If we check cross-references to the variables, we can see that they’re actually written to:

And if we try to decompile the function doing it, we’ll see some “interesting” messages:

And again, the addresses mentioned are all in the same supposedly-constant segment.

So we can make this conclusion: despite the name, the segment is not actually constant. How do we tell the decompiler that? 

The easiest solution is to add the Write flag to the segment’s permission. This can be done via the Edit > Segments > Edit segment… command (shortcut Alt-S).

After refreshing the pseudocode (F5), we no longer see the red warning or mentions of “write access to const memory”. And if we go back to the previously “too short” function, it now has all the checks which were missing:

See also:

Igor’s tip of the week #16: Cross-references

Igor’s tip of the week #56: String literals in pseudocode

Decompiler Manual > Tips and tricks: Constant memory