Add code to emulate switch and ldelem
This commit is contained in:
parent
de8e63d140
commit
98936364f7
|
@ -173,6 +173,12 @@ namespace de4dot.blocks {
|
||||||
replaceLastInstrsWithBranch(1, target);
|
replaceLastInstrsWithBranch(1, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void replaceSwitchWithBranch(Block target) {
|
||||||
|
if (LastInstr.OpCode.Code != Code.Switch)
|
||||||
|
throw new ApplicationException("Last instruction is not a switch");
|
||||||
|
replaceLastInstrsWithBranch(1, target);
|
||||||
|
}
|
||||||
|
|
||||||
public void removeDeadBlock() {
|
public void removeDeadBlock() {
|
||||||
if (sources.Count != 0)
|
if (sources.Count != 0)
|
||||||
throw new ApplicationException("Trying to remove a non-dead block");
|
throw new ApplicationException("Trying to remove a non-dead block");
|
||||||
|
|
|
@ -65,6 +65,7 @@ namespace de4dot.blocks.cflow {
|
||||||
case Code.Brfalse_S:return emulate_Brfalse();
|
case Code.Brfalse_S:return emulate_Brfalse();
|
||||||
case Code.Brtrue:
|
case Code.Brtrue:
|
||||||
case Code.Brtrue_S: return emulate_Brtrue();
|
case Code.Brtrue_S: return emulate_Brtrue();
|
||||||
|
case Code.Switch: return emulate_Switch();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -78,13 +79,16 @@ namespace de4dot.blocks.cflow {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool emulateBranch(int stackArgs, bool isTaken) {
|
bool emulateBranch(int stackArgs, bool isTaken) {
|
||||||
|
popPushedArgs(stackArgs);
|
||||||
|
block.replaceBccWithBranch(isTaken);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void popPushedArgs(int stackArgs) {
|
||||||
// Pop the arguments to the bcc instruction. The dead code remover will get rid of the
|
// Pop the arguments to the bcc instruction. The dead code remover will get rid of the
|
||||||
// pop and any pushed arguments. Insert the pops just before the bcc instr.
|
// pop and any pushed arguments. Insert the pops just before the bcc instr.
|
||||||
for (int i = 0; i < stackArgs; i++)
|
for (int i = 0; i < stackArgs; i++)
|
||||||
block.insert(block.Instructions.Count - 1, Instruction.Create(OpCodes.Pop));
|
block.insert(block.Instructions.Count - 1, Instruction.Create(OpCodes.Pop));
|
||||||
|
|
||||||
block.replaceBccWithBranch(isTaken);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool emulate_Beq() {
|
bool emulate_Beq() {
|
||||||
|
@ -236,5 +240,27 @@ namespace de4dot.blocks.cflow {
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool emulate_Switch() {
|
||||||
|
var val1 = instructionEmulator.pop();
|
||||||
|
|
||||||
|
if (val1.valueType != ValueType.Int32)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var int1 = (Int32Value)val1;
|
||||||
|
if (!int1.allBitsValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int index = int1.value;
|
||||||
|
var targets = block.Targets;
|
||||||
|
Block newTarget;
|
||||||
|
if (targets == null || index < 0 || index >= targets.Count)
|
||||||
|
newTarget = block.FallThrough;
|
||||||
|
else
|
||||||
|
newTarget = targets[index];
|
||||||
|
popPushedArgs(1);
|
||||||
|
block.replaceSwitchWithBranch(newTarget);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,6 +261,7 @@ namespace de4dot.blocks.cflow {
|
||||||
case Code.Ldelem_U1: valueStack.pop(2); valueStack.push(Int32Value.createUnknownUInt8()); break;
|
case Code.Ldelem_U1: valueStack.pop(2); valueStack.push(Int32Value.createUnknownUInt8()); break;
|
||||||
case Code.Ldelem_U2: valueStack.pop(2); valueStack.push(Int32Value.createUnknownUInt16()); break;
|
case Code.Ldelem_U2: valueStack.pop(2); valueStack.push(Int32Value.createUnknownUInt16()); break;
|
||||||
case Code.Ldelem_U4: valueStack.pop(2); valueStack.push(Int32Value.createUnknown()); break;
|
case Code.Ldelem_U4: valueStack.pop(2); valueStack.push(Int32Value.createUnknown()); break;
|
||||||
|
case Code.Ldelem_Any:valueStack.pop(2); valueStack.push(getUnknownValue(instr.Operand as TypeReference)); break;
|
||||||
|
|
||||||
case Code.Ldind_I1: valueStack.pop(); valueStack.push(Int32Value.createUnknown()); break;
|
case Code.Ldind_I1: valueStack.pop(); valueStack.push(Int32Value.createUnknown()); break;
|
||||||
case Code.Ldind_I2: valueStack.pop(); valueStack.push(Int32Value.createUnknown()); break;
|
case Code.Ldind_I2: valueStack.pop(); valueStack.push(Int32Value.createUnknown()); break;
|
||||||
|
@ -327,7 +328,6 @@ namespace de4dot.blocks.cflow {
|
||||||
case Code.Initobj:
|
case Code.Initobj:
|
||||||
case Code.Jmp:
|
case Code.Jmp:
|
||||||
case Code.Ldelema:
|
case Code.Ldelema:
|
||||||
case Code.Ldelem_Any:
|
|
||||||
case Code.Ldelem_I:
|
case Code.Ldelem_I:
|
||||||
case Code.Ldelem_R4:
|
case Code.Ldelem_R4:
|
||||||
case Code.Ldelem_R8:
|
case Code.Ldelem_R8:
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace de4dot.blocks.cflow {
|
||||||
return validMask != NO_UNKNOWN_BITS;
|
return validMask != NO_UNKNOWN_BITS;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool allBitsValid() {
|
public bool allBitsValid() {
|
||||||
return !hasUnknownBits();
|
return !hasUnknownBits();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user