public static Expression GetEnumExpression(TypeDefinition enumDefinition, LiteralExpression targetedValue, TypeSystem typeSystem) { V_0 = EnumHelper.GetEnumBitSize(enumDefinition); V_1 = (long)0; V_4 = targetedValue.get_Value().GetType().get_FullName(); if (V_4 != null) { if (String.op_Equality(V_4, "System.Int32")) { if (V_0 != 32) { V_1 = (long)((Int32)targetedValue.get_Value()); } else { V_1 = (ulong)((Int32)targetedValue.get_Value()); } } else { if (String.op_Equality(V_4, "System.Int64")) { V_1 = (Int64)targetedValue.get_Value(); } else { if (String.op_Equality(V_4, "System.UInt32")) { V_1 = (ulong)((UInt32)targetedValue.get_Value()); } else { if (String.op_Equality(V_4, "System.UInt64")) { V_1 = (UInt64)targetedValue.get_Value(); } else { if (String.op_Equality(V_4, "System.Byte")) { V_1 = (ulong)((Byte)targetedValue.get_Value()); } else { if (String.op_Equality(V_4, "System.SByte")) { V_1 = (long)((SByte)targetedValue.get_Value()); } else { if (String.op_Equality(V_4, "System.Int16")) { V_1 = (long)((Int16)targetedValue.get_Value()); } else { if (String.op_Equality(V_4, "System.UInt16")) { V_1 = (ulong)((UInt16)targetedValue.get_Value()); } } } } } } } } } stackVariable10 = enumDefinition.get_Fields(); V_2 = new List <FieldDefinition>(); V_6 = stackVariable10.GetEnumerator(); try { while (V_6.MoveNext()) { V_7 = V_6.get_Current(); if (V_7.get_Constant() == null || V_7.get_Constant().get_Value() == null) { continue; } V_8 = (long)0; V_4 = V_7.get_Constant().get_Value().GetType().get_FullName(); if (V_4 != null) { if (String.op_Equality(V_4, "System.Int32")) { V_8 = (ulong)((Int32)V_7.get_Constant().get_Value()); } else { if (String.op_Equality(V_4, "System.UInt32")) { V_8 = (ulong)((UInt32)V_7.get_Constant().get_Value()); } else { if (String.op_Equality(V_4, "System.Byte")) { V_8 = (ulong)((Byte)V_7.get_Constant().get_Value()); } else { if (String.op_Equality(V_4, "System.SByte")) { V_8 = (ulong)((byte)((SByte)V_7.get_Constant().get_Value())); } else { if (String.op_Equality(V_4, "System.Int16")) { V_8 = (ulong)((ushort)((Int16)V_7.get_Constant().get_Value())); } else { if (String.op_Equality(V_4, "System.UInt16")) { V_8 = (ulong)((UInt16)V_7.get_Constant().get_Value()); } else { if (String.op_Equality(V_4, "System.Int64")) { V_8 = (Int64)V_7.get_Constant().get_Value(); } else { if (String.op_Equality(V_4, "System.UInt64")) { V_8 = (UInt64)V_7.get_Constant().get_Value(); } } } } } } } } } if (V_8 != V_1) { if (V_8 == 0 || V_8 | V_1 != V_1) { continue; } V_2.Add(V_7); } else { V_9 = new EnumExpression(V_7, targetedValue.get_UnderlyingSameMethodInstructions()); goto Label1; } } goto Label0; } finally { V_6.Dispose(); } Label1: return(V_9); Label0: if (V_2.get_Count() < 2) { return(targetedValue); } V_3 = new BinaryExpression(21, new EnumExpression(V_2.get_Item(0), null), new EnumExpression(V_2.get_Item(1), null), typeSystem, null, false); V_3.set_ExpressionType(enumDefinition); V_10 = 2; while (V_10 < V_2.get_Count()) { V_3 = new BinaryExpression(21, V_3, new EnumExpression(V_2.get_Item(V_10), null), typeSystem, null, false); V_3.set_ExpressionType(enumDefinition); V_10 = V_10 + 1; } return(V_3.CloneAndAttachInstructions(targetedValue.get_UnderlyingSameMethodInstructions())); }
private void MarkOptimizationAndCaseBlocks(InstructionBlock block, SwitchData data) { Queue <InstructionBlock> queue = new Queue <InstructionBlock>(); HashSet <int> visited = new HashSet <int>(); foreach (InstructionBlock successor in block.Successors) { queue.Enqueue(successor); } while (queue.Count > 0) { InstructionBlock current = queue.Dequeue(); visited.Add(current.First.Offset); if (IsOptimizationBlock(this.blockExpressions[current.First.Offset], data.OptimizationVariable)) { // The first successor of an optimization block is either another optimization block // or case block. Either case we want to enqueue it. InstructionBlock firstSuccessor = current.Successors[0]; if (!visited.Contains(firstSuccessor.First.Offset)) { queue.Enqueue(firstSuccessor); } // The second (and last) successor of an optimization block can be unconditional jump. // In that case we need to first remove it. Then we examine the new last successor of // the optimization block. InstructionBlock lastSuccessor = MarkSecondSuccessorForRemovalIfItIsUnconditionalJump(current); // We enqueue the last successor of an optimization block only if it's another optimization block. // This is done, because if we have an optimization block, which last successor is jump to the // switch's next statement (the first statement after the actual switch) and this next statement // have the same structure as the case blocks, this will cause unexpected behavior and wrong decompilation. if (!visited.Contains(lastSuccessor.First.Offset) && IsOptimizationBlock(this.blockExpressions[current.First.Offset], data.OptimizationVariable)) { queue.Enqueue(lastSuccessor); } blocksToBeRemoved.Add(current.First.Offset); } else if (IsCaseBlock(this.blockExpressions[current.First.Offset], data.SwitchExpression) || IsNullCaseBlock(this.blockExpressions[current.First.Offset], data.SwitchExpression)) { switchBlocksToCasesMap[block.First.Offset].Add(current.First.Offset); InstructionBlock secondSuccessor = current.Successors[1]; if (IsEmptyStringCaseBlock(this.blockExpressions[secondSuccessor.First.Offset], data.SwitchExpression)) { // The first successor is jump to the next/default statement, so we merge the current block with // its second successor, which contains the lenght check. The first successor of the current block // and the second successor of current block's second successor are exactly the same block. In this // case it will be marked for removal by the MarkSecondSuccessorForRemovalIfItIsUnconditionalJump // invocation below, so there is no need for us to mark it here. current.Last = secondSuccessor.Last; current.Successors = secondSuccessor.Successors; // We change the someExpr == null binary expression, so it became someExpr == "". BinaryExpression binary = this.blockExpressions[current.First.Offset][0] as BinaryExpression; binary.Right = new LiteralExpression("", this.methodContext.Method.Module.TypeSystem, null); // Preserve the instructions from the second block as instructions of the binary expression. IEnumerable <Instruction> secondSuccessorInstructions = this.blockExpressions[secondSuccessor.First.Offset][0].UnderlyingSameMethodInstructions; binary = binary.CloneAndAttachInstructions(secondSuccessorInstructions) as BinaryExpression; // Wrap the binary expression in unary with operator "None", because it should have the exact // same structure as the normal cases in order next steps of switch by string building to work. this.blockExpressions[current.First.Offset][0] = new UnaryExpression(UnaryOperator.None, binary, null); this.blocksToBeRemoved.Add(secondSuccessor.First.Offset); } // If the second successor of the case block is unconditional jump we want to remove it. // This is done, because later we take all case blocks and connect them one to each other. // All case blocks can have different unconditional jump block used to jump the the next statement // (the statement after the switch statement). Later we connect all the case blocks in a chain // and we want to be sure that there is only one way to go the next statement, and that there are // no unreachable unconditional jump blocks. MarkSecondSuccessorForRemovalIfItIsUnconditionalJump(current); } } }
public static Expression GetEnumExpression(TypeDefinition enumDefinition, LiteralExpression targetedValue, TypeSystem typeSystem) { int enumDefinitionUnderlyingTypeSize = GetEnumBitSize(enumDefinition); /// This depends on the unchecked context, which is default for C# ulong value = 0; switch (targetedValue.Value.GetType().FullName) { case "System.Int32": /// This is done, so that the same size extension is used when casting the literal's value to ulong /// and when casting anum's contstants to ulong. /// Otherwise, casting int -1 and long -1 to ulong will yield different results. if (enumDefinitionUnderlyingTypeSize == 32) { value = (uint)(int)targetedValue.Value; } else { value = (ulong)(int)targetedValue.Value; } break; case "System.Int64": value = (ulong)(long)targetedValue.Value; break; case "System.UInt32": value = (uint)targetedValue.Value; break; case "System.UInt64": value = (ulong)targetedValue.Value; break; // The types below should not be present at any point, but are added just to complete all the possible cases. case "System.Byte": value = (byte)targetedValue.Value; break; case "System.SByte": value = (ulong)(sbyte)targetedValue.Value; break; case "System.Int16": value = (ulong)(short)targetedValue.Value; break; case "System.UInt16": value = (ushort)targetedValue.Value; break; } Collection <FieldDefinition> fields = enumDefinition.Fields; List <FieldDefinition> enumFields = new List <FieldDefinition>(); foreach (FieldDefinition currentField in fields) { if (currentField.Constant != null && currentField.Constant.Value != null) { ulong fieldValue = 0; switch (currentField.Constant.Value.GetType().FullName) { case "System.Int32": // most common case fieldValue = (uint)(int)(currentField.Constant.Value); break; case "System.UInt32": fieldValue = (uint)(currentField.Constant.Value); break; case "System.Byte": fieldValue = (byte)(currentField.Constant.Value); break; case "System.SByte": fieldValue = (byte)(sbyte)(currentField.Constant.Value); break; case "System.Int16": fieldValue = (ushort)(short)(currentField.Constant.Value); break; case "System.UInt16": fieldValue = (ushort)(currentField.Constant.Value); break; case "System.Int64": fieldValue = (ulong)(long)(currentField.Constant.Value); break; case "System.UInt64": fieldValue = (ulong)(currentField.Constant.Value); break; } if (fieldValue == value) { return(new EnumExpression(currentField, targetedValue.UnderlyingSameMethodInstructions)); } if (fieldValue != 0 && (fieldValue | value) == value) //if (IsPartOfValue(fieldValue, value)) { ///Then this one of the flags, used to generate the value. enumFields.Add(currentField); } } } ///Generate the expression of the flags. if (enumFields.Count < 2) { return(targetedValue); } Expression result = new BinaryExpression(BinaryOperator.BitwiseOr, new EnumExpression(enumFields[0], null), new EnumExpression(enumFields[1], null), typeSystem, null); result.ExpressionType = enumDefinition; for (int i = 2; i < enumFields.Count; i++) { result = new BinaryExpression(BinaryOperator.BitwiseOr, result, new EnumExpression(enumFields[i], null), typeSystem, null); result.ExpressionType = enumDefinition; } return(result.CloneAndAttachInstructions(targetedValue.UnderlyingSameMethodInstructions)); }