Ghidra: MSVC Float comparison to 0.0 not decompiled properly

Created on 8 Mar 2019  路  3Comments  路  Source: NationalSecurityAgency/ghidra

Describe the bug
On 32 bit x86 architecture (and possibly 64bit), MSVC generates a specific pattern to test equality to zero of floating point numbers (see: https://stackoverflow.com/a/46772747). This pattern is incorrectly decompiled.

To Reproduce
decompile this pattern:

0f 57 c0            XORPS       XMM0,XMM0
0f 2e c8            UCOMISS     XMM1,XMM0
9f                  LAHF
f6 c4 44            TEST        AH,44h
7b 28               JNP         loc_equal_zero

The code is decompiled as:
if(false) { ... }

Once the dead code removal is deactivated.

Expected behavior
The expected behavior is:
if ( value_in_XMM1 != 0.0 ) { ... }

Environment:

  • OS: Windows 10
  • Version 9.0
Processox86 Bug

All 3 comments

Small and temporary solution, this is wrong check, but fix decompiler output. The template for conditional jumps doesn't work correctly according to some instructions. I think for static analysis this is not very affected, but it's not the best solution.

Should be added in line 3408:

:JNP rel8       is vexMode=0 & byte=0x7B; rel8                                  { if (PF==1) goto rel8; }
:JNP rel16      is vexMode=0 & opsize=0 & byte=0x0F; byte=0x8B; rel16           { if (PF==1) goto rel16; }
:JNP rel32      is vexMode=0 & opsize=1 & byte=0x0F; byte=0x8B; rel32           { if (PF==1) goto rel32; }

line 7813

define pcodeop fucomiss;
:UCOMISS         XmmReg, m32      is vexMode=0 & mandover=0 & byte=0x0F; byte=0x2E; ( XmmReg & XmmReg_Da ) ... & m32 {  fucompe(XmmReg_Da, m32); fucomiss(XmmReg_Da, m32);}

code:
image

before:
image
after:
image

One more way to fix:

define pcodeop fucomiss;
:UCOMISS         XmmReg, m32      is vexMode=0 & mandover=0 & byte=0x0F; byte=0x2E; ( XmmReg & XmmReg_Da ) ... & m32 {  fucompe(XmmReg_Da, m32); fucomiss(XmmReg_Da, m32);}

and

macro fucompe(val1, val2) {
    PF = nan(val1) || nan(val2);
    ZF = PF | ( val1 f== val2 );
    CF = PF | ( val1 f< val2 );   

    PF = 1;
    OF = 0;
    AF = 0;
    SF = 0;
}

Only with JNP this macros destroyed decompiler output, because sometime PF=0.

Thanks for the feedback.

Should be fixed in master now and in upcoming 9.2. We've added full support for the parity flag.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

0x6d696368 picture 0x6d696368  路  17Comments

ghost picture ghost  路  29Comments

mumbel picture mumbel  路  29Comments

niedabao1 picture niedabao1  路  23Comments

cattrace picture cattrace  路  20Comments