Skip to content

"while" structring loses induction statements, was: "if" structuring doesn't work properly in tricky CFGs #31

@maximumspatium

Description

@maximumspatium

SAB fails to decompile the following real-world code:

sub_201100:
$cr0.eq = (i32)$r4 == 0
$cr0.lt = (i32)$r4 < 0
$cr0.gt = (i32)$r4 > 0
$r11 = 0
if ($cr0.eq) goto loc_20114C

loc_20110C:
$ctr = $r4
$r12 = $r3 - 1
goto loc_201128

loc_201118:
if ($cr0.gt) goto loc_201124

loc_20111C:
$r0 = $r9 + 0x1
$r10 = $r0 & 0xff

loc_201124:
$r11 = $r10

loc_201128:
$ea = ($r12 + 0x1)
$r3 = *(u8*)$ea
$r12 = $ea
$r9 = $r3 + $r11
$r10 = $r9 & 0xff
$cr0.eq = (i32)$r10 == (i32)$r11
$cr0.lt = (i32)$r10 < (i32)$r11
$cr0.gt = (i32)$r10 > (i32)$r11
$ctr -= 1
if ($ctr != 0) goto loc_201118

loc_20113C:
if ($cr0.gt) goto loc_201148

loc_201140:
$r4 = $r9 + 0x1
$r10 = $r4 & 0xff

loc_201148:
$r11 = $r10

loc_20114C:
$r3 = $r11
return

It returns

AttributeError: 'REG' object has no attribute 'op'

After some debugging, I was able to spot the place of the failure: match_if is unable to negate the following condition:

edge('13','20') {
    'cond': COND($cr0.gt_0)
}

My bet is that $cr0.gt cannot be substituted because its value changes across basic blocks. So it's left as is. Finally, match_if() fails because it expects COND to be an expression, not REG.

Any idea how to fix that?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions