예제 #1
0
        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);
                }
            }
        }
예제 #3
0
        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));
        }