Add validMask field to Int32/64Value
This commit is contained in:
parent
05065d6ac7
commit
718cdb0487
|
@ -37,6 +37,9 @@
|
||||||
<Compile Include="BlocksSorter.cs" />
|
<Compile Include="BlocksSorter.cs" />
|
||||||
<Compile Include="cflow\BlockControlFlowDeobfuscator.cs" />
|
<Compile Include="cflow\BlockControlFlowDeobfuscator.cs" />
|
||||||
<Compile Include="cflow\InstructionEmulator.cs" />
|
<Compile Include="cflow\InstructionEmulator.cs" />
|
||||||
|
<Compile Include="cflow\Int32Value.cs" />
|
||||||
|
<Compile Include="cflow\Int64Value.cs" />
|
||||||
|
<Compile Include="cflow\Real8Value.cs" />
|
||||||
<Compile Include="cflow\Value.cs" />
|
<Compile Include="cflow\Value.cs" />
|
||||||
<Compile Include="cflow\ValueStack.cs" />
|
<Compile Include="cflow\ValueStack.cs" />
|
||||||
<Compile Include="CodeGenerator.cs" />
|
<Compile Include="CodeGenerator.cs" />
|
||||||
|
|
|
@ -71,6 +71,12 @@ namespace de4dot.blocks.cflow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool emulateBranch(int stackArgs, Bool3 cond) {
|
||||||
|
if (cond == Bool3.Unknown)
|
||||||
|
return false;
|
||||||
|
return emulateBranch(stackArgs, cond == Bool3.True);
|
||||||
|
}
|
||||||
|
|
||||||
bool emulateBranch(int stackArgs, bool isTaken) {
|
bool emulateBranch(int stackArgs, bool isTaken) {
|
||||||
// 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.
|
||||||
|
@ -85,461 +91,133 @@ namespace de4dot.blocks.cflow {
|
||||||
var val2 = instructionEmulator.pop();
|
var val2 = instructionEmulator.pop();
|
||||||
var val1 = instructionEmulator.pop();
|
var val1 = instructionEmulator.pop();
|
||||||
|
|
||||||
//TODO: If it's an unknown int32/64, push 1 if val1 is same ref as val2
|
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32)
|
||||||
|
return emulateBranch(2, Int32Value.compareEq((Int32Value)val1, (Int32Value)val2));
|
||||||
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32) {
|
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64)
|
||||||
var int1 = (Int32Value)val1;
|
return emulateBranch(2, Int64Value.compareEq((Int64Value)val1, (Int64Value)val2));
|
||||||
var int2 = (Int32Value)val2;
|
else if (val1.valueType == ValueType.Null && val2.valueType == ValueType.Null)
|
||||||
return emulateBranch(2, int1.value == int2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64) {
|
|
||||||
var long1 = (Int64Value)val1;
|
|
||||||
var long2 = (Int64Value)val2;
|
|
||||||
return emulateBranch(2, long1.value == long2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Real8 && val2.valueType == ValueType.Real8) {
|
|
||||||
var real1 = (Real8Value)val1;
|
|
||||||
var real2 = (Real8Value)val2;
|
|
||||||
return emulateBranch(2, real1.value == real2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Null && val2.valueType == ValueType.Null) {
|
|
||||||
return emulateBranch(2, true);
|
return emulateBranch(2, true);
|
||||||
}
|
else
|
||||||
else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool emulate_Bne_Un() {
|
bool emulate_Bne_Un() {
|
||||||
var val2 = instructionEmulator.pop();
|
var val2 = instructionEmulator.pop();
|
||||||
var val1 = instructionEmulator.pop();
|
var val1 = instructionEmulator.pop();
|
||||||
|
|
||||||
//TODO: If it's an unknown int32/64, push 1 if val1 is same ref as val2
|
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32)
|
||||||
|
return emulateBranch(2, Int32Value.compareNeq((Int32Value)val1, (Int32Value)val2));
|
||||||
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32) {
|
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64)
|
||||||
var int1 = (Int32Value)val1;
|
return emulateBranch(2, Int64Value.compareNeq((Int64Value)val1, (Int64Value)val2));
|
||||||
var int2 = (Int32Value)val2;
|
else if (val1.valueType == ValueType.Null && val2.valueType == ValueType.Null)
|
||||||
return emulateBranch(2, (uint)int1.value != (uint)int2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64) {
|
|
||||||
var long1 = (Int64Value)val1;
|
|
||||||
var long2 = (Int64Value)val2;
|
|
||||||
return emulateBranch(2, (ulong)long1.value != (ulong)long2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Real8 && val2.valueType == ValueType.Real8) {
|
|
||||||
var real1 = (Real8Value)val1;
|
|
||||||
var real2 = (Real8Value)val2;
|
|
||||||
return emulateBranch(2, real1.value != real2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Null && val2.valueType == ValueType.Null) {
|
|
||||||
return emulateBranch(2, false);
|
return emulateBranch(2, false);
|
||||||
}
|
else
|
||||||
else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool emulate_Bge() {
|
bool emulate_Bge() {
|
||||||
var val2 = instructionEmulator.pop();
|
var val2 = instructionEmulator.pop();
|
||||||
var val1 = instructionEmulator.pop();
|
var val1 = instructionEmulator.pop();
|
||||||
|
|
||||||
//TODO: Support floats
|
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32)
|
||||||
|
return emulateBranch(2, Int32Value.compareGe((Int32Value)val1, (Int32Value)val2));
|
||||||
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32) {
|
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64)
|
||||||
var int1 = (Int32Value)val1;
|
return emulateBranch(2, Int64Value.compareGe((Int64Value)val1, (Int64Value)val2));
|
||||||
var int2 = (Int32Value)val2;
|
|
||||||
return emulateBranch(2, int1.value >= int2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64) {
|
|
||||||
var long1 = (Int64Value)val1;
|
|
||||||
var long2 = (Int64Value)val2;
|
|
||||||
return emulateBranch(2, long1.value >= long2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int32) {
|
|
||||||
var int1 = (Int32Value)val1;
|
|
||||||
if (int1.value == int.MaxValue)
|
|
||||||
return emulateBranch(2, true); // max >= x => true
|
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (val2.valueType == ValueType.Int32) {
|
|
||||||
var int2 = (Int32Value)val2;
|
|
||||||
if (int2.value == int.MinValue)
|
|
||||||
return emulateBranch(2, true); // x >= min => true
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int64) {
|
|
||||||
var long1 = (Int64Value)val1;
|
|
||||||
if (long1.value == long.MaxValue)
|
|
||||||
return emulateBranch(2, true); // max >= x => true
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (val2.valueType == ValueType.Int64) {
|
|
||||||
var long2 = (Int64Value)val2;
|
|
||||||
if (long2.value == long.MinValue)
|
|
||||||
return emulateBranch(2, true); // x >= min => true
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool emulate_Bge_Un() {
|
bool emulate_Bge_Un() {
|
||||||
var val2 = instructionEmulator.pop();
|
var val2 = instructionEmulator.pop();
|
||||||
var val1 = instructionEmulator.pop();
|
var val1 = instructionEmulator.pop();
|
||||||
|
|
||||||
//TODO: Support floats
|
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32)
|
||||||
|
return emulateBranch(2, Int32Value.compareGe_Un((Int32Value)val1, (Int32Value)val2));
|
||||||
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32) {
|
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64)
|
||||||
var int1 = (Int32Value)val1;
|
return emulateBranch(2, Int64Value.compareGe_Un((Int64Value)val1, (Int64Value)val2));
|
||||||
var int2 = (Int32Value)val2;
|
|
||||||
return emulateBranch(2, (uint)int1.value >= (uint)int2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64) {
|
|
||||||
var long1 = (Int64Value)val1;
|
|
||||||
var long2 = (Int64Value)val2;
|
|
||||||
return emulateBranch(2, (ulong)long1.value >= (ulong)long2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int32) {
|
|
||||||
var int1 = (Int32Value)val1;
|
|
||||||
if ((uint)int1.value == uint.MaxValue)
|
|
||||||
return emulateBranch(2, true); // max >= x => true
|
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (val2.valueType == ValueType.Int32) {
|
|
||||||
var int2 = (Int32Value)val2;
|
|
||||||
if ((uint)int2.value == uint.MinValue)
|
|
||||||
return emulateBranch(2, true); // x >= min => true
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int64) {
|
|
||||||
var long1 = (Int64Value)val1;
|
|
||||||
if ((ulong)long1.value == ulong.MaxValue)
|
|
||||||
return emulateBranch(2, true); // max >= x => true
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (val2.valueType == ValueType.Int64) {
|
|
||||||
var long2 = (Int64Value)val2;
|
|
||||||
if ((ulong)long2.value == ulong.MinValue)
|
|
||||||
return emulateBranch(2, true); // x >= min => true
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool emulate_Bgt() {
|
bool emulate_Bgt() {
|
||||||
var val2 = instructionEmulator.pop();
|
var val2 = instructionEmulator.pop();
|
||||||
var val1 = instructionEmulator.pop();
|
var val1 = instructionEmulator.pop();
|
||||||
|
|
||||||
//TODO: Support floats
|
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32)
|
||||||
|
return emulateBranch(2, Int32Value.compareGt((Int32Value)val1, (Int32Value)val2));
|
||||||
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32) {
|
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64)
|
||||||
var int1 = (Int32Value)val1;
|
return emulateBranch(2, Int64Value.compareGt((Int64Value)val1, (Int64Value)val2));
|
||||||
var int2 = (Int32Value)val2;
|
|
||||||
return emulateBranch(2, int1.value > int2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64) {
|
|
||||||
var long1 = (Int64Value)val1;
|
|
||||||
var long2 = (Int64Value)val2;
|
|
||||||
return emulateBranch(2, long1.value > long2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int32) {
|
|
||||||
var int1 = (Int32Value)val1;
|
|
||||||
if (int1.value == int.MinValue)
|
|
||||||
return emulateBranch(2, false); // min > x => false
|
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (val2.valueType == ValueType.Int32) {
|
|
||||||
var int2 = (Int32Value)val2;
|
|
||||||
if (int2.value == int.MaxValue)
|
|
||||||
return emulateBranch(2, false); // x > max => false
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int64) {
|
|
||||||
var long1 = (Int64Value)val1;
|
|
||||||
if (long1.value == long.MinValue)
|
|
||||||
return emulateBranch(2, false); // min > x => false
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (val2.valueType == ValueType.Int64) {
|
|
||||||
var long2 = (Int64Value)val2;
|
|
||||||
if (long2.value == long.MaxValue)
|
|
||||||
return emulateBranch(2, false); // x > max => false
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool emulate_Bgt_Un() {
|
bool emulate_Bgt_Un() {
|
||||||
var val2 = instructionEmulator.pop();
|
var val2 = instructionEmulator.pop();
|
||||||
var val1 = instructionEmulator.pop();
|
var val1 = instructionEmulator.pop();
|
||||||
|
|
||||||
//TODO: Support floats
|
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32)
|
||||||
|
return emulateBranch(2, Int32Value.compareGt_Un((Int32Value)val1, (Int32Value)val2));
|
||||||
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32) {
|
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64)
|
||||||
var int1 = (Int32Value)val1;
|
return emulateBranch(2, Int64Value.compareGt_Un((Int64Value)val1, (Int64Value)val2));
|
||||||
var int2 = (Int32Value)val2;
|
|
||||||
return emulateBranch(2, (uint)int1.value > (uint)int2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64) {
|
|
||||||
var long1 = (Int64Value)val1;
|
|
||||||
var long2 = (Int64Value)val2;
|
|
||||||
return emulateBranch(2, (ulong)long1.value > (ulong)long2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int32) {
|
|
||||||
var int1 = (Int32Value)val1;
|
|
||||||
if ((uint)int1.value == uint.MinValue)
|
|
||||||
return emulateBranch(2, false); // min > x => false
|
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (val2.valueType == ValueType.Int32) {
|
|
||||||
var int2 = (Int32Value)val2;
|
|
||||||
if ((uint)int2.value == uint.MaxValue)
|
|
||||||
return emulateBranch(2, false); // x > max => false
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int64) {
|
|
||||||
var long1 = (Int64Value)val1;
|
|
||||||
if ((ulong)long1.value == ulong.MinValue)
|
|
||||||
return emulateBranch(2, false); // min > x => false
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (val2.valueType == ValueType.Int64) {
|
|
||||||
var long2 = (Int64Value)val2;
|
|
||||||
if ((ulong)long2.value == ulong.MaxValue)
|
|
||||||
return emulateBranch(2, false); // x > max => false
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool emulate_Ble() {
|
bool emulate_Ble() {
|
||||||
var val2 = instructionEmulator.pop();
|
var val2 = instructionEmulator.pop();
|
||||||
var val1 = instructionEmulator.pop();
|
var val1 = instructionEmulator.pop();
|
||||||
|
|
||||||
//TODO: Support floats
|
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32)
|
||||||
|
return emulateBranch(2, Int32Value.compareLe((Int32Value)val1, (Int32Value)val2));
|
||||||
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32) {
|
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64)
|
||||||
var int1 = (Int32Value)val1;
|
return emulateBranch(2, Int64Value.compareLe((Int64Value)val1, (Int64Value)val2));
|
||||||
var int2 = (Int32Value)val2;
|
|
||||||
return emulateBranch(2, int1.value <= int2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64) {
|
|
||||||
var long1 = (Int64Value)val1;
|
|
||||||
var long2 = (Int64Value)val2;
|
|
||||||
return emulateBranch(2, long1.value <= long2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int32) {
|
|
||||||
var int1 = (Int32Value)val1;
|
|
||||||
if (int1.value == int.MinValue)
|
|
||||||
return emulateBranch(2, true); // min <= x => true
|
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (val2.valueType == ValueType.Int32) {
|
|
||||||
var int2 = (Int32Value)val2;
|
|
||||||
if (int2.value == int.MaxValue)
|
|
||||||
return emulateBranch(2, true); // x <= max => true
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int64) {
|
|
||||||
var long1 = (Int64Value)val1;
|
|
||||||
if (long1.value == long.MinValue)
|
|
||||||
return emulateBranch(2, true); // min <= x => true
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (val2.valueType == ValueType.Int64) {
|
|
||||||
var long2 = (Int64Value)val2;
|
|
||||||
if (long2.value == long.MaxValue)
|
|
||||||
return emulateBranch(2, true); // x <= max => true
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool emulate_Ble_Un() {
|
bool emulate_Ble_Un() {
|
||||||
var val2 = instructionEmulator.pop();
|
var val2 = instructionEmulator.pop();
|
||||||
var val1 = instructionEmulator.pop();
|
var val1 = instructionEmulator.pop();
|
||||||
|
|
||||||
//TODO: Support floats
|
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32)
|
||||||
|
return emulateBranch(2, Int32Value.compareLe_Un((Int32Value)val1, (Int32Value)val2));
|
||||||
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32) {
|
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64)
|
||||||
var int1 = (Int32Value)val1;
|
return emulateBranch(2, Int64Value.compareLe_Un((Int64Value)val1, (Int64Value)val2));
|
||||||
var int2 = (Int32Value)val2;
|
|
||||||
return emulateBranch(2, (uint)int1.value <= (uint)int2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64) {
|
|
||||||
var long1 = (Int64Value)val1;
|
|
||||||
var long2 = (Int64Value)val2;
|
|
||||||
return emulateBranch(2, (ulong)long1.value <= (ulong)long2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int32) {
|
|
||||||
var int1 = (Int32Value)val1;
|
|
||||||
if ((uint)int1.value == uint.MinValue)
|
|
||||||
return emulateBranch(2, true); // min <= x => true
|
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (val2.valueType == ValueType.Int32) {
|
|
||||||
var int2 = (Int32Value)val2;
|
|
||||||
if ((uint)int2.value == uint.MaxValue)
|
|
||||||
return emulateBranch(2, true); // x <= max => true
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int64) {
|
|
||||||
var long1 = (Int64Value)val1;
|
|
||||||
if ((ulong)long1.value == ulong.MinValue)
|
|
||||||
return emulateBranch(2, true); // min <= x => true
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (val2.valueType == ValueType.Int64) {
|
|
||||||
var long2 = (Int64Value)val2;
|
|
||||||
if ((ulong)long2.value == ulong.MaxValue)
|
|
||||||
return emulateBranch(2, true); // x <= max => true
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool emulate_Blt() {
|
bool emulate_Blt() {
|
||||||
var val2 = instructionEmulator.pop();
|
var val2 = instructionEmulator.pop();
|
||||||
var val1 = instructionEmulator.pop();
|
var val1 = instructionEmulator.pop();
|
||||||
|
|
||||||
//TODO: Support floats
|
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32)
|
||||||
|
return emulateBranch(2, Int32Value.compareLt((Int32Value)val1, (Int32Value)val2));
|
||||||
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32) {
|
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64)
|
||||||
var int1 = (Int32Value)val1;
|
return emulateBranch(2, Int64Value.compareLt((Int64Value)val1, (Int64Value)val2));
|
||||||
var int2 = (Int32Value)val2;
|
|
||||||
return emulateBranch(2, int1.value < int2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64) {
|
|
||||||
var long1 = (Int64Value)val1;
|
|
||||||
var long2 = (Int64Value)val2;
|
|
||||||
return emulateBranch(2, long1.value < long2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int32) {
|
|
||||||
var int1 = (Int32Value)val1;
|
|
||||||
if (int1.value == int.MaxValue)
|
|
||||||
return emulateBranch(2, false); // max < x => false
|
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (val2.valueType == ValueType.Int32) {
|
|
||||||
var int2 = (Int32Value)val2;
|
|
||||||
if (int2.value == int.MinValue)
|
|
||||||
return emulateBranch(2, false); // x < min => false
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int64) {
|
|
||||||
var long1 = (Int64Value)val1;
|
|
||||||
if (long1.value == long.MaxValue)
|
|
||||||
return emulateBranch(2, false); // max < x => false
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (val2.valueType == ValueType.Int64) {
|
|
||||||
var long2 = (Int64Value)val2;
|
|
||||||
if (long2.value == long.MinValue)
|
|
||||||
return emulateBranch(2, false); // x < min => false
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool emulate_Blt_Un() {
|
bool emulate_Blt_Un() {
|
||||||
var val2 = instructionEmulator.pop();
|
var val2 = instructionEmulator.pop();
|
||||||
var val1 = instructionEmulator.pop();
|
var val1 = instructionEmulator.pop();
|
||||||
|
|
||||||
//TODO: Support floats
|
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32)
|
||||||
|
return emulateBranch(2, Int32Value.compareLt_Un((Int32Value)val1, (Int32Value)val2));
|
||||||
if (val1.valueType == ValueType.Int32 && val2.valueType == ValueType.Int32) {
|
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64)
|
||||||
var int1 = (Int32Value)val1;
|
return emulateBranch(2, Int64Value.compareLt_Un((Int64Value)val1, (Int64Value)val2));
|
||||||
var int2 = (Int32Value)val2;
|
|
||||||
return emulateBranch(2, (uint)int1.value < (uint)int2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int64 && val2.valueType == ValueType.Int64) {
|
|
||||||
var long1 = (Int64Value)val1;
|
|
||||||
var long2 = (Int64Value)val2;
|
|
||||||
return emulateBranch(2, (ulong)long1.value < (ulong)long2.value);
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int32) {
|
|
||||||
var int1 = (Int32Value)val1;
|
|
||||||
if ((uint)int1.value == uint.MaxValue)
|
|
||||||
return emulateBranch(2, false); // max < x => false
|
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (val2.valueType == ValueType.Int32) {
|
|
||||||
var int2 = (Int32Value)val2;
|
|
||||||
if ((uint)int2.value == uint.MinValue)
|
|
||||||
return emulateBranch(2, false); // x < min => false
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (val1.valueType == ValueType.Int64) {
|
|
||||||
var long1 = (Int64Value)val1;
|
|
||||||
if ((ulong)long1.value == ulong.MaxValue)
|
|
||||||
return emulateBranch(2, false); // max < x => false
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (val2.valueType == ValueType.Int64) {
|
|
||||||
var long2 = (Int64Value)val2;
|
|
||||||
if ((ulong)long2.value == ulong.MinValue)
|
|
||||||
return emulateBranch(2, false); // x < min => false
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool emulate_Brfalse() {
|
bool emulate_Brfalse() {
|
||||||
var val1 = instructionEmulator.pop();
|
var val1 = instructionEmulator.pop();
|
||||||
|
|
||||||
//TODO: Support floats
|
|
||||||
|
|
||||||
if (val1.valueType == ValueType.Int32)
|
if (val1.valueType == ValueType.Int32)
|
||||||
return emulateBranch(1, ((Int32Value)val1).value == 0);
|
return emulateBranch(1, Int32Value.compareFalse((Int32Value)val1));
|
||||||
else if (val1.valueType == ValueType.Int64)
|
else if (val1.valueType == ValueType.Int64)
|
||||||
return emulateBranch(1, ((Int64Value)val1).value == 0);
|
return emulateBranch(1, Int64Value.compareFalse((Int64Value)val1));
|
||||||
else if (val1.valueType == ValueType.Null)
|
else if (val1.valueType == ValueType.Null)
|
||||||
return emulateBranch(1, true);
|
return emulateBranch(1, true);
|
||||||
else
|
else
|
||||||
|
@ -549,12 +227,10 @@ namespace de4dot.blocks.cflow {
|
||||||
bool emulate_Brtrue() {
|
bool emulate_Brtrue() {
|
||||||
var val1 = instructionEmulator.pop();
|
var val1 = instructionEmulator.pop();
|
||||||
|
|
||||||
//TODO: Support floats
|
|
||||||
|
|
||||||
if (val1.valueType == ValueType.Int32)
|
if (val1.valueType == ValueType.Int32)
|
||||||
return emulateBranch(1, ((Int32Value)val1).value != 0);
|
return emulateBranch(1, Int32Value.compareTrue((Int32Value)val1));
|
||||||
else if (val1.valueType == ValueType.Int64)
|
else if (val1.valueType == ValueType.Int64)
|
||||||
return emulateBranch(1, ((Int64Value)val1).value != 0);
|
return emulateBranch(1, Int64Value.compareTrue((Int64Value)val1));
|
||||||
else if (val1.valueType == ValueType.Null)
|
else if (val1.valueType == ValueType.Null)
|
||||||
return emulateBranch(1, false);
|
return emulateBranch(1, false);
|
||||||
else
|
else
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
488
blocks/cflow/Int32Value.cs
Normal file
488
blocks/cflow/Int32Value.cs
Normal file
|
@ -0,0 +1,488 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2011 de4dot@gmail.com
|
||||||
|
|
||||||
|
This file is part of de4dot.
|
||||||
|
|
||||||
|
de4dot is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
de4dot is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace de4dot.blocks.cflow {
|
||||||
|
class Int32Value : Value {
|
||||||
|
const uint NO_UNKNOWN_BITS = uint.MaxValue;
|
||||||
|
public readonly int value;
|
||||||
|
public readonly uint validMask;
|
||||||
|
|
||||||
|
public Int32Value(int value)
|
||||||
|
: base(ValueType.Int32) {
|
||||||
|
this.value = value;
|
||||||
|
this.validMask = NO_UNKNOWN_BITS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Int32Value(int value, uint validMask)
|
||||||
|
: base(ValueType.Int32) {
|
||||||
|
this.value = value;
|
||||||
|
this.validMask = validMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool hasUnknownBits() {
|
||||||
|
return validMask != NO_UNKNOWN_BITS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool allBitsValid() {
|
||||||
|
return !hasUnknownBits();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isBitValid(int n) {
|
||||||
|
return isBitValid(validMask, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isBitValid(uint validMask, int n) {
|
||||||
|
return (validMask & (1U << n)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value createUnknownBool() {
|
||||||
|
return new Int32Value(0, NO_UNKNOWN_BITS << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value createUnknownUInt8() {
|
||||||
|
return new Int32Value(0, NO_UNKNOWN_BITS << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value createUnknownUInt16() {
|
||||||
|
return new Int32Value(0, NO_UNKNOWN_BITS << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value createUnknown() {
|
||||||
|
return new Int32Value(0, 0U);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool isZero() {
|
||||||
|
return hasValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool hasValue(int value) {
|
||||||
|
return allBitsValid() && this.value == value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool hasValue(uint value) {
|
||||||
|
return hasValue((int)value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_U1(Int32Value a) {
|
||||||
|
return Conv_U1(a.value, a.validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_U1(Int64Value a) {
|
||||||
|
return Conv_U1((int)a.value, (uint)a.validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_U1(int value, uint validMask) {
|
||||||
|
//TODO: Doc says that result is sign-extended. You zero-extend it. Is that correct?
|
||||||
|
value = (int)(byte)value;
|
||||||
|
validMask |= NO_UNKNOWN_BITS << 8;
|
||||||
|
return new Int32Value(value, validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_U1(Real8Value a) {
|
||||||
|
//TODO: Doc says that result is sign-extended. You zero-extend it. Is that correct?
|
||||||
|
return new Int32Value((int)(byte)a.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_I1(Int32Value a) {
|
||||||
|
return Conv_I1(a.value, a.validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_I1(Int64Value a) {
|
||||||
|
return Conv_I1((int)a.value, (uint)a.validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_I1(int value, uint validMask) {
|
||||||
|
value = (int)(sbyte)value;
|
||||||
|
if (isBitValid(validMask, 7))
|
||||||
|
validMask |= NO_UNKNOWN_BITS << 8;
|
||||||
|
else
|
||||||
|
validMask &= ~(NO_UNKNOWN_BITS << 8);
|
||||||
|
return new Int32Value(value, validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_I1(Real8Value a) {
|
||||||
|
return new Int32Value((int)(sbyte)a.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_U2(Int32Value a) {
|
||||||
|
return Conv_U2(a.value, a.validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_U2(Int64Value a) {
|
||||||
|
return Conv_U2((int)a.value, (uint)a.validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_U2(int value, uint validMask) {
|
||||||
|
//TODO: Doc says that result is sign-extended. You zero-extend it. Is that correct?
|
||||||
|
value = (int)(ushort)value;
|
||||||
|
validMask |= NO_UNKNOWN_BITS << 16;
|
||||||
|
return new Int32Value(value, validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_U2(Real8Value a) {
|
||||||
|
//TODO: Doc says that result is sign-extended. You zero-extend it. Is that correct?
|
||||||
|
return new Int32Value((int)(ushort)a.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_I2(Int32Value a) {
|
||||||
|
return Conv_I2(a.value, a.validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_I2(Int64Value a) {
|
||||||
|
return Conv_I2((int)a.value, (uint)a.validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_I2(int value, uint validMask) {
|
||||||
|
value = (int)(short)value;
|
||||||
|
if (isBitValid(validMask, 15))
|
||||||
|
validMask |= NO_UNKNOWN_BITS << 16;
|
||||||
|
else
|
||||||
|
validMask &= ~(NO_UNKNOWN_BITS << 16);
|
||||||
|
return new Int32Value(value, validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_I2(Real8Value a) {
|
||||||
|
return new Int32Value((int)(short)a.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_U4(Int32Value a) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_U4(Int64Value a) {
|
||||||
|
return new Int32Value((int)(uint)a.value, (uint)a.validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_U4(Real8Value a) {
|
||||||
|
return new Int32Value((int)(uint)a.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_I4(Int32Value a) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_I4(Int64Value a) {
|
||||||
|
return new Int32Value((int)a.value, (uint)a.validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Conv_I4(Real8Value a) {
|
||||||
|
return new Int32Value((int)a.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Add(Int32Value a, Int32Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return new Int32Value(a.value + b.value);
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Sub(Int32Value a, Int32Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return new Int32Value(a.value - b.value);
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Mul(Int32Value a, Int32Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return new Int32Value(a.value * b.value);
|
||||||
|
if (a.isZero() || b.isZero())
|
||||||
|
return new Int32Value(0);
|
||||||
|
if (a.hasValue(1))
|
||||||
|
return b;
|
||||||
|
if (b.hasValue(1))
|
||||||
|
return a;
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Div(Int32Value a, Int32Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid()) {
|
||||||
|
try {
|
||||||
|
return new Int32Value(a.value / b.value);
|
||||||
|
}
|
||||||
|
catch (ArithmeticException) {
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (b.hasValue(1))
|
||||||
|
return a;
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Div_Un(Int32Value a, Int32Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid()) {
|
||||||
|
try {
|
||||||
|
return new Int32Value((int)((uint)a.value / (uint)b.value));
|
||||||
|
}
|
||||||
|
catch (ArithmeticException) {
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (b.hasValue(1))
|
||||||
|
return a;
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Rem(Int32Value a, Int32Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid()) {
|
||||||
|
try {
|
||||||
|
return new Int32Value(a.value % b.value);
|
||||||
|
}
|
||||||
|
catch (ArithmeticException) {
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (b.hasValue(1))
|
||||||
|
return new Int32Value(0);
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Rem_Un(Int32Value a, Int32Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid()) {
|
||||||
|
try {
|
||||||
|
return new Int32Value((int)((uint)a.value % (uint)b.value));
|
||||||
|
}
|
||||||
|
catch (ArithmeticException) {
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (b.hasValue(1))
|
||||||
|
return new Int32Value(0);
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Neg(Int32Value a) {
|
||||||
|
if (a.allBitsValid())
|
||||||
|
return new Int32Value(-a.value);
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value And(Int32Value a, Int32Value b) {
|
||||||
|
int av = a.value, bv = b.value;
|
||||||
|
uint am = a.validMask, bm = b.validMask;
|
||||||
|
return new Int32Value(av & bv, (uint)((am & bm) | ((av & am) ^ am) | ((bv & bm) ^ bm)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Or(Int32Value a, Int32Value b) {
|
||||||
|
int av = a.value, bv = b.value;
|
||||||
|
uint am = a.validMask, bm = b.validMask;
|
||||||
|
return new Int32Value(av | bv, (uint)((am & bm) | (av & am) | (bv & bm)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Xor(Int32Value a, Int32Value b) {
|
||||||
|
if (ReferenceEquals(a, b))
|
||||||
|
return new Int32Value(0);
|
||||||
|
int av = a.value, bv = b.value;
|
||||||
|
uint am = a.validMask, bm = b.validMask;
|
||||||
|
return new Int32Value(av ^ bv, (uint)(am & bm));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Not(Int32Value a) {
|
||||||
|
return new Int32Value(~a.value, a.validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Shl(Int32Value a, Int32Value b) {
|
||||||
|
if (b.hasUnknownBits())
|
||||||
|
return createUnknown();
|
||||||
|
if (b.value == 0)
|
||||||
|
return a;
|
||||||
|
if (b.value < 0 || b.value >= sizeof(int) * 8)
|
||||||
|
return createUnknown();
|
||||||
|
int shift = b.value;
|
||||||
|
uint validMask = (a.validMask << shift) | (uint.MaxValue >> (sizeof(int) * 8 - shift));
|
||||||
|
return new Int32Value(a.value << shift, validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Shr(Int32Value a, Int32Value b) {
|
||||||
|
if (b.hasUnknownBits())
|
||||||
|
return createUnknown();
|
||||||
|
if (b.value == 0)
|
||||||
|
return a;
|
||||||
|
if (b.value < 0 || b.value >= sizeof(int) * 8)
|
||||||
|
return createUnknown();
|
||||||
|
int shift = b.value;
|
||||||
|
uint validMask = a.validMask >> shift;
|
||||||
|
if (a.isBitValid(sizeof(int) * 8 - 1))
|
||||||
|
validMask |= (uint.MaxValue << (sizeof(int) * 8 - shift));
|
||||||
|
return new Int32Value(a.value >> shift, validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Shr_Un(Int32Value a, Int32Value b) {
|
||||||
|
if (b.hasUnknownBits())
|
||||||
|
return createUnknown();
|
||||||
|
if (b.value == 0)
|
||||||
|
return a;
|
||||||
|
if (b.value < 0 || b.value >= sizeof(int) * 8)
|
||||||
|
return createUnknown();
|
||||||
|
int shift = b.value;
|
||||||
|
uint validMask = (a.validMask >> shift) | (uint.MaxValue << (sizeof(int) * 8 - shift));
|
||||||
|
return new Int32Value((int)((uint)a.value >> shift), validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Int32Value create(Bool3 b) {
|
||||||
|
switch (b) {
|
||||||
|
case Bool3.False: return new Int32Value(0);
|
||||||
|
case Bool3.True: return new Int32Value(1);
|
||||||
|
default: return createUnknown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Ceq(Int32Value a, Int32Value b) {
|
||||||
|
return create(compareEq(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Cgt(Int32Value a, Int32Value b) {
|
||||||
|
return create(compareGt(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Cgt_Un(Int32Value a, Int32Value b) {
|
||||||
|
return create(compareGt_Un(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Clt(Int32Value a, Int32Value b) {
|
||||||
|
return create(compareLt(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Clt_Un(Int32Value a, Int32Value b) {
|
||||||
|
return create(compareLt_Un(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareEq(Int32Value a, Int32Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return a.value == b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (ReferenceEquals(a, b))
|
||||||
|
return Bool3.True;
|
||||||
|
if ((a.value & a.validMask & b.validMask) != (b.value & a.validMask & b.validMask))
|
||||||
|
return Bool3.False;
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareNeq(Int32Value a, Int32Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return a.value != b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (ReferenceEquals(a, b))
|
||||||
|
return Bool3.False;
|
||||||
|
if ((a.value & a.validMask & b.validMask) != (b.value & a.validMask & b.validMask))
|
||||||
|
return Bool3.True;
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareGt(Int32Value a, Int32Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return a.value > b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (a.hasValue(int.MinValue))
|
||||||
|
return Bool3.False; // min > x => false
|
||||||
|
if (b.hasValue(int.MaxValue))
|
||||||
|
return Bool3.False; // x > max => false
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareGt_Un(Int32Value a, Int32Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return (uint)a.value > (uint)b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (a.hasValue(uint.MinValue))
|
||||||
|
return Bool3.False; // min > x => false
|
||||||
|
if (b.hasValue(uint.MaxValue))
|
||||||
|
return Bool3.False; // x > max => false
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareGe(Int32Value a, Int32Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return a.value >= b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (a.hasValue(int.MaxValue))
|
||||||
|
return Bool3.False; // max >= x => true
|
||||||
|
if (b.hasValue(int.MinValue))
|
||||||
|
return Bool3.False; // x >= min => true
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareGe_Un(Int32Value a, Int32Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return (uint)a.value >= (uint)b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (a.hasValue(uint.MaxValue))
|
||||||
|
return Bool3.False; // max >= x => true
|
||||||
|
if (b.hasValue(uint.MinValue))
|
||||||
|
return Bool3.False; // x >= min => true
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareLe(Int32Value a, Int32Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return a.value <= b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (a.hasValue(int.MinValue))
|
||||||
|
return Bool3.False; // min <= x => true
|
||||||
|
if (b.hasValue(int.MaxValue))
|
||||||
|
return Bool3.False; // x <= max => true
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareLe_Un(Int32Value a, Int32Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return (uint)a.value <= (uint)b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (a.hasValue(uint.MinValue))
|
||||||
|
return Bool3.False; // min <= x => true
|
||||||
|
if (b.hasValue(uint.MaxValue))
|
||||||
|
return Bool3.False; // x <= max => true
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareLt(Int32Value a, Int32Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return a.value < b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (a.hasValue(int.MaxValue))
|
||||||
|
return Bool3.False; // max < x => false
|
||||||
|
if (b.hasValue(int.MinValue))
|
||||||
|
return Bool3.False; // x < min => false
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareLt_Un(Int32Value a, Int32Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return (uint)a.value < (uint)b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (a.hasValue(uint.MaxValue))
|
||||||
|
return Bool3.False; // max < x => false
|
||||||
|
if (b.hasValue(uint.MinValue))
|
||||||
|
return Bool3.False; // x < min => false
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareTrue(Int32Value a) {
|
||||||
|
if (a.allBitsValid())
|
||||||
|
return a.value != 0 ? Bool3.True : Bool3.False;
|
||||||
|
if ((a.value & a.validMask) != 0)
|
||||||
|
return Bool3.True;
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareFalse(Int32Value a) {
|
||||||
|
if (a.allBitsValid())
|
||||||
|
return a.value == 0 ? Bool3.True : Bool3.False;
|
||||||
|
if ((a.value & a.validMask) != 0)
|
||||||
|
return Bool3.False;
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() {
|
||||||
|
if (allBitsValid())
|
||||||
|
return value.ToString();
|
||||||
|
return string.Format("0x{0:X8}({1:X8})", value, validMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
403
blocks/cflow/Int64Value.cs
Normal file
403
blocks/cflow/Int64Value.cs
Normal file
|
@ -0,0 +1,403 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2011 de4dot@gmail.com
|
||||||
|
|
||||||
|
This file is part of de4dot.
|
||||||
|
|
||||||
|
de4dot is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
de4dot is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace de4dot.blocks.cflow {
|
||||||
|
class Int64Value : Value {
|
||||||
|
const ulong NO_UNKNOWN_BITS = ulong.MaxValue;
|
||||||
|
public readonly long value;
|
||||||
|
public readonly ulong validMask;
|
||||||
|
|
||||||
|
public Int64Value(long value)
|
||||||
|
: base(ValueType.Int64) {
|
||||||
|
this.value = value;
|
||||||
|
this.validMask = NO_UNKNOWN_BITS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Int64Value(long value, ulong validMask)
|
||||||
|
: base(ValueType.Int64) {
|
||||||
|
this.value = value;
|
||||||
|
this.validMask = validMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasUnknownBits() {
|
||||||
|
return validMask != NO_UNKNOWN_BITS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool allBitsValid() {
|
||||||
|
return !hasUnknownBits();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isBitValid(int n) {
|
||||||
|
return isBitValid(validMask, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isBitValid(ulong validMask, int n) {
|
||||||
|
return (validMask & (1UL << n)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value createUnknown() {
|
||||||
|
return new Int64Value(0, 0UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool isZero() {
|
||||||
|
return hasValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool hasValue(long value) {
|
||||||
|
return allBitsValid() && this.value == value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool hasValue(ulong value) {
|
||||||
|
return hasValue((long)value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Conv_U8(Int32Value a) {
|
||||||
|
//TODO: Doc says that result is sign-extended. You zero-extend it. Is that correct?
|
||||||
|
long value = (long)(ulong)(uint)a.value;
|
||||||
|
ulong validMask = a.validMask | (NO_UNKNOWN_BITS << 32);
|
||||||
|
return new Int64Value(value, validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Conv_U8(Int64Value a) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Conv_U8(Real8Value a) {
|
||||||
|
return new Int64Value((long)(ulong)a.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Conv_I8(Int32Value a) {
|
||||||
|
long value = a.value;
|
||||||
|
ulong validMask = a.validMask;
|
||||||
|
if (isBitValid(validMask, 31))
|
||||||
|
validMask |= NO_UNKNOWN_BITS << 32;
|
||||||
|
else
|
||||||
|
validMask &= ~(NO_UNKNOWN_BITS << 32);
|
||||||
|
return new Int64Value(value, validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Conv_I8(Int64Value a) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Conv_I8(Real8Value a) {
|
||||||
|
return new Int64Value((long)a.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Add(Int64Value a, Int64Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return new Int64Value(a.value + b.value);
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Sub(Int64Value a, Int64Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return new Int64Value(a.value - b.value);
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Mul(Int64Value a, Int64Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return new Int64Value(a.value * b.value);
|
||||||
|
if (a.isZero() || b.isZero())
|
||||||
|
return new Int64Value(0);
|
||||||
|
if (a.hasValue(1))
|
||||||
|
return b;
|
||||||
|
if (b.hasValue(1))
|
||||||
|
return a;
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Div(Int64Value a, Int64Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid()) {
|
||||||
|
try {
|
||||||
|
return new Int64Value(a.value / b.value);
|
||||||
|
}
|
||||||
|
catch (ArithmeticException) {
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (b.hasValue(1))
|
||||||
|
return a;
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Div_Un(Int64Value a, Int64Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid()) {
|
||||||
|
try {
|
||||||
|
return new Int64Value((int)((uint)a.value / (uint)b.value));
|
||||||
|
}
|
||||||
|
catch (ArithmeticException) {
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (b.hasValue(1))
|
||||||
|
return a;
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Rem(Int64Value a, Int64Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid()) {
|
||||||
|
try {
|
||||||
|
return new Int64Value(a.value % b.value);
|
||||||
|
}
|
||||||
|
catch (ArithmeticException) {
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (b.hasValue(1))
|
||||||
|
return new Int64Value(0);
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Rem_Un(Int64Value a, Int64Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid()) {
|
||||||
|
try {
|
||||||
|
return new Int64Value((int)((uint)a.value % (uint)b.value));
|
||||||
|
}
|
||||||
|
catch (ArithmeticException) {
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (b.hasValue(1))
|
||||||
|
return new Int64Value(0);
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Neg(Int64Value a) {
|
||||||
|
if (a.allBitsValid())
|
||||||
|
return new Int64Value(-a.value);
|
||||||
|
return createUnknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value And(Int64Value a, Int64Value b) {
|
||||||
|
long av = a.value, bv = b.value;
|
||||||
|
ulong am = a.validMask, bm = b.validMask;
|
||||||
|
return new Int64Value(av & bv, (am & bm) | (((ulong)av & am) ^ am) | (((ulong)bv & bm) ^ bm));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Or(Int64Value a, Int64Value b) {
|
||||||
|
long av = a.value, bv = b.value;
|
||||||
|
ulong am = a.validMask, bm = b.validMask;
|
||||||
|
return new Int64Value(av | bv, (am & bm) | ((ulong)av & am) | ((ulong)bv & bm));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Xor(Int64Value a, Int64Value b) {
|
||||||
|
if (ReferenceEquals(a, b))
|
||||||
|
return new Int64Value(0);
|
||||||
|
long av = a.value, bv = b.value;
|
||||||
|
ulong am = a.validMask, bm = b.validMask;
|
||||||
|
return new Int64Value(av ^ bv, am & bm);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Not(Int64Value a) {
|
||||||
|
return new Int64Value(~a.value, a.validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Shl(Int64Value a, Int32Value b) {
|
||||||
|
if (b.hasUnknownBits())
|
||||||
|
return createUnknown();
|
||||||
|
if (b.value == 0)
|
||||||
|
return a;
|
||||||
|
if (b.value < 0 || b.value >= sizeof(long) * 8)
|
||||||
|
return createUnknown();
|
||||||
|
int shift = b.value;
|
||||||
|
ulong validMask = (a.validMask << shift) | (ulong.MaxValue >> (sizeof(long) * 8 - shift));
|
||||||
|
return new Int64Value(a.value << shift, validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Shr(Int64Value a, Int32Value b) {
|
||||||
|
if (b.hasUnknownBits())
|
||||||
|
return createUnknown();
|
||||||
|
if (b.value == 0)
|
||||||
|
return a;
|
||||||
|
if (b.value < 0 || b.value >= sizeof(long) * 8)
|
||||||
|
return createUnknown();
|
||||||
|
int shift = b.value;
|
||||||
|
ulong validMask = a.validMask >> shift;
|
||||||
|
if (a.isBitValid(sizeof(long) * 8 - 1))
|
||||||
|
validMask |= (ulong.MaxValue << (sizeof(long) * 8 - shift));
|
||||||
|
return new Int64Value(a.value >> shift, validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64Value Shr_Un(Int64Value a, Int32Value b) {
|
||||||
|
if (b.hasUnknownBits())
|
||||||
|
return createUnknown();
|
||||||
|
if (b.value == 0)
|
||||||
|
return a;
|
||||||
|
if (b.value < 0 || b.value >= sizeof(long) * 8)
|
||||||
|
return createUnknown();
|
||||||
|
int shift = b.value;
|
||||||
|
ulong validMask = (a.validMask >> shift) | (ulong.MaxValue << (sizeof(long) * 8 - shift));
|
||||||
|
return new Int64Value((long)((ulong)a.value >> shift), validMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Int32Value create(Bool3 b) {
|
||||||
|
switch (b) {
|
||||||
|
case Bool3.False: return new Int32Value(0);
|
||||||
|
case Bool3.True: return new Int32Value(1);
|
||||||
|
default: return Int32Value.createUnknown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Ceq(Int64Value a, Int64Value b) {
|
||||||
|
return create(compareEq(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Cgt(Int64Value a, Int64Value b) {
|
||||||
|
return create(compareGt(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Cgt_Un(Int64Value a, Int64Value b) {
|
||||||
|
return create(compareGt_Un(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Clt(Int64Value a, Int64Value b) {
|
||||||
|
return create(compareLt(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int32Value Clt_Un(Int64Value a, Int64Value b) {
|
||||||
|
return create(compareLt_Un(a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareEq(Int64Value a, Int64Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return a.value == b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (ReferenceEquals(a, b))
|
||||||
|
return Bool3.True;
|
||||||
|
if (((ulong)a.value & a.validMask & b.validMask) != ((ulong)b.value & a.validMask & b.validMask))
|
||||||
|
return Bool3.False;
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareNeq(Int64Value a, Int64Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return a.value != b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (ReferenceEquals(a, b))
|
||||||
|
return Bool3.False;
|
||||||
|
if (((ulong)a.value & a.validMask & b.validMask) != ((ulong)b.value & a.validMask & b.validMask))
|
||||||
|
return Bool3.True;
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareGt(Int64Value a, Int64Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return a.value > b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (a.hasValue(int.MinValue))
|
||||||
|
return Bool3.False; // min > x => false
|
||||||
|
if (b.hasValue(int.MaxValue))
|
||||||
|
return Bool3.False; // x > max => false
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareGt_Un(Int64Value a, Int64Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return (uint)a.value > (uint)b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (a.hasValue(uint.MinValue))
|
||||||
|
return Bool3.False; // min > x => false
|
||||||
|
if (b.hasValue(uint.MaxValue))
|
||||||
|
return Bool3.False; // x > max => false
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareGe(Int64Value a, Int64Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return a.value >= b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (a.hasValue(int.MaxValue))
|
||||||
|
return Bool3.False; // max >= x => true
|
||||||
|
if (b.hasValue(int.MinValue))
|
||||||
|
return Bool3.False; // x >= min => true
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareGe_Un(Int64Value a, Int64Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return (uint)a.value >= (uint)b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (a.hasValue(uint.MaxValue))
|
||||||
|
return Bool3.False; // max >= x => true
|
||||||
|
if (b.hasValue(uint.MinValue))
|
||||||
|
return Bool3.False; // x >= min => true
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareLe(Int64Value a, Int64Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return a.value <= b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (a.hasValue(int.MinValue))
|
||||||
|
return Bool3.False; // min <= x => true
|
||||||
|
if (b.hasValue(int.MaxValue))
|
||||||
|
return Bool3.False; // x <= max => true
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareLe_Un(Int64Value a, Int64Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return (uint)a.value <= (uint)b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (a.hasValue(uint.MinValue))
|
||||||
|
return Bool3.False; // min <= x => true
|
||||||
|
if (b.hasValue(uint.MaxValue))
|
||||||
|
return Bool3.False; // x <= max => true
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareLt(Int64Value a, Int64Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return a.value < b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (a.hasValue(int.MaxValue))
|
||||||
|
return Bool3.False; // max < x => false
|
||||||
|
if (b.hasValue(int.MinValue))
|
||||||
|
return Bool3.False; // x < min => false
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareLt_Un(Int64Value a, Int64Value b) {
|
||||||
|
if (a.allBitsValid() && b.allBitsValid())
|
||||||
|
return (uint)a.value < (uint)b.value ? Bool3.True : Bool3.False;
|
||||||
|
if (a.hasValue(uint.MaxValue))
|
||||||
|
return Bool3.False; // max < x => false
|
||||||
|
if (b.hasValue(uint.MinValue))
|
||||||
|
return Bool3.False; // x < min => false
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareTrue(Int64Value a) {
|
||||||
|
if (a.allBitsValid())
|
||||||
|
return a.value != 0 ? Bool3.True : Bool3.False;
|
||||||
|
if (((ulong)a.value & a.validMask) != 0)
|
||||||
|
return Bool3.True;
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bool3 compareFalse(Int64Value a) {
|
||||||
|
if (a.allBitsValid())
|
||||||
|
return a.value == 0 ? Bool3.True : Bool3.False;
|
||||||
|
if (((ulong)a.value & a.validMask) != 0)
|
||||||
|
return Bool3.False;
|
||||||
|
return Bool3.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() {
|
||||||
|
if (allBitsValid())
|
||||||
|
return value.ToString();
|
||||||
|
return string.Format("0x{0:X8}L({1:X8})", value, validMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
53
blocks/cflow/Real8Value.cs
Normal file
53
blocks/cflow/Real8Value.cs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2011 de4dot@gmail.com
|
||||||
|
|
||||||
|
This file is part of de4dot.
|
||||||
|
|
||||||
|
de4dot is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
de4dot is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace de4dot.blocks.cflow {
|
||||||
|
class Real8Value : Value {
|
||||||
|
public readonly double value;
|
||||||
|
|
||||||
|
public Real8Value(double value)
|
||||||
|
: base(ValueType.Real8) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Real8Value Add(Real8Value a, Real8Value b) {
|
||||||
|
return new Real8Value(a.value + b.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Real8Value Sub(Real8Value a, Real8Value b) {
|
||||||
|
return new Real8Value(a.value - b.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Real8Value Mul(Real8Value a, Real8Value b) {
|
||||||
|
return new Real8Value(a.value * b.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Real8Value Div(Real8Value a, Real8Value b) {
|
||||||
|
return new Real8Value(a.value / b.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Real8Value Rem(Real8Value a, Real8Value b) {
|
||||||
|
return new Real8Value(a.value % b.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Real8Value Neg(Real8Value a) {
|
||||||
|
return new Real8Value(-a.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,6 +28,12 @@ namespace de4dot.blocks.cflow {
|
||||||
String,
|
String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Bool3 {
|
||||||
|
Unknown = -1,
|
||||||
|
False,
|
||||||
|
True,
|
||||||
|
}
|
||||||
|
|
||||||
abstract class Value {
|
abstract class Value {
|
||||||
public readonly ValueType valueType;
|
public readonly ValueType valueType;
|
||||||
|
|
||||||
|
@ -72,45 +78,6 @@ namespace de4dot.blocks.cflow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Int32Value : Value {
|
|
||||||
public readonly int value;
|
|
||||||
|
|
||||||
public Int32Value(int value)
|
|
||||||
: base(ValueType.Int32) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() {
|
|
||||||
return value.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Int64Value : Value {
|
|
||||||
public readonly long value;
|
|
||||||
|
|
||||||
public Int64Value(long value)
|
|
||||||
: base(ValueType.Int64) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() {
|
|
||||||
return value.ToString() + "L";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Real8Value : Value {
|
|
||||||
public readonly double value;
|
|
||||||
|
|
||||||
public Real8Value(double value)
|
|
||||||
: base(ValueType.Real8) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() {
|
|
||||||
return value.ToString() + "D";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class StringValue : Value {
|
class StringValue : Value {
|
||||||
public readonly string value;
|
public readonly string value;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user