}
@Override
public Set<AbstractState> visit(RTLAssume stmt) {
Architecture arch = Program.getProgram().getArchitecture();
/////////
// Special case for non-exit edges of x86 REP/REPNZ prefixes (for loops using ecx)
if (stmt.getSource().getType() == RTLGoto.Type.STRING_LENGTH_CHECK) {
BasedNumberElement loopCounter = getValue(arch.loopCounter());
if (loopCounter.isTop() || loopCounter.isNumberTop()) {
X86Instruction instr = (X86Instruction)Program.getProgram().getInstruction(stmt.getAddress());
BasedNumberValuation post = copyThisState();
if (instr.hasEsiBasedMemorySource()) {
logger.debug(stmt.getLabel() + ": ecx is unknown in REP/REPNZ, widening esi");
post.setValue(arch.stringSource(), new BasedNumberElement(
getValue(arch.stringSource()).getRegion(),
NumberElement.getTop(arch.getAddressBitWidth())));
}
if (instr.hasEdiBasedMemoryTarget()) {
logger.debug(stmt.getLabel() + ": ecx is unknown in REP/REPNZ, widening edi");
post.setValue(arch.stringTarget(), new BasedNumberElement(
getValue(arch.stringTarget()).getRegion(),
NumberElement.getTop(arch.getAddressBitWidth())));
}
// STRING_LENGTH_CHECK assumptions are ecx == 0 or !(ecx == 0)
RTLOperation operation = (RTLOperation)stmt.getAssumption();
if (operation.getOperator() == Operator.EQUAL) {
assert operation.getOperands()[0] == arch.loopCounter();
assert ((RTLNumber)operation.getOperands()[1]).longValue() == 0;
post.setValue(arch.loopCounter(), abstractEval(operation.getOperands()[1]));
}
return Collections.singleton((AbstractState)post);
}
}