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);
|
||||
}
|
||||
|
||||
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() {
|
||||
if (sources.Count != 0)
|
||||
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.Brtrue:
|
||||
case Code.Brtrue_S: return emulate_Brtrue();
|
||||
case Code.Switch: return emulate_Switch();
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
@ -78,13 +79,16 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
|
||||
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 and any pushed arguments. Insert the pops just before the bcc instr.
|
||||
for (int i = 0; i < stackArgs; i++)
|
||||
block.insert(block.Instructions.Count - 1, Instruction.Create(OpCodes.Pop));
|
||||
|
||||
block.replaceBccWithBranch(isTaken);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool emulate_Beq() {
|
||||
|
@ -236,5 +240,27 @@ namespace de4dot.blocks.cflow {
|
|||
else
|
||||
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_U2: valueStack.pop(2); valueStack.push(Int32Value.createUnknownUInt16()); 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_I2: valueStack.pop(); valueStack.push(Int32Value.createUnknown()); break;
|
||||
|
@ -327,7 +328,6 @@ namespace de4dot.blocks.cflow {
|
|||
case Code.Initobj:
|
||||
case Code.Jmp:
|
||||
case Code.Ldelema:
|
||||
case Code.Ldelem_Any:
|
||||
case Code.Ldelem_I:
|
||||
case Code.Ldelem_R4:
|
||||
case Code.Ldelem_R8:
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace de4dot.blocks.cflow {
|
|||
return validMask != NO_UNKNOWN_BITS;
|
||||
}
|
||||
|
||||
bool allBitsValid() {
|
||||
public bool allBitsValid() {
|
||||
return !hasUnknownBits();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user