예제 #1
0
        public static ConstantPoolInfo Read(ClassReader classReader)
        {
            ushort           tag = classReader.ReadU1();
            ConstantPoolInfo constantPoolInfo = null;

            switch (tag)
            {
            case 7:
                constantPoolInfo = new ConstantClass(); break;

            case 9:
                constantPoolInfo = new ConstantFieldRef(); break;

            case 10:
                constantPoolInfo = new ConstantMethodRef(); break;

            case 11:
                constantPoolInfo = new ConstantInterfaceMethodRef(); break;

            case 8:
                constantPoolInfo = new ConstantString(); break;

            case 3:
                constantPoolInfo = new ConstantInteger(); break;

            case 4:
                constantPoolInfo = new ConstantFloat(); break;

            case 5:
                constantPoolInfo = new ConstantLong(); break;

            case 6:
                constantPoolInfo = new ConstantDouble(); break;

            case 12:
                constantPoolInfo = new ConstantNameAndType(); break;

            case 1:
                constantPoolInfo = new ConstantUtf8(); break;

            case 15:
                constantPoolInfo = new ConstantMethodHandle(); break;

            case 16:
                constantPoolInfo = new ConstantMethodType(); break;

            case 18:
                constantPoolInfo = new ConstantInvokeDynamic(); break;

            default:
                throw new Exception("ClassFileError:constantPoolInfo incorrect");
            }
            constantPoolInfo.Tag = tag;
            constantPoolInfo.ReadConstantPoolInfo(classReader);

            return(constantPoolInfo);
        }
예제 #2
0
        public static ImmutableList <int?> GetEvaluationStackDepths(DisassembledMethod disassembledMethod, ReadOnlyCollection <ConstantPoolEntry> constantPool, ReadOnlyCollection <ExceptionTableEntry> exceptionTable)
        {
            Contract.Requires <ArgumentNullException>(disassembledMethod != null, "disassembledMethod");
            Contract.Requires <ArgumentNullException>(constantPool != null, "constantPool");
            Contract.Requires <ArgumentNullException>(exceptionTable != null, "exceptionTable");

            Contract.Ensures(Contract.Result <ImmutableList <int?> >() != null);
            Contract.Ensures(Contract.Result <ImmutableList <int?> >().Count == disassembledMethod.Instructions.Count);

            int?[]      depths    = new int?[disassembledMethod.Instructions.Count];
            Queue <int> workQueue = new Queue <int>();

            // can obviously start at the beginning of the method
            depths[0] = 0;
            workQueue.Enqueue(0);
            // can also start inside each exception handler
            foreach (var entry in exceptionTable)
            {
                int nextIndex = disassembledMethod.Instructions.FindIndex(i => i.Offset == entry.HandlerOffset);
                if (!depths[nextIndex].HasValue)
                {
                    depths[nextIndex] = 1;
                    workQueue.Enqueue(nextIndex);
                }
            }

            while (workQueue.Count > 0)
            {
                int             index       = workQueue.Dequeue();
                JavaInstruction instruction = disassembledMethod.Instructions[index];
                int             netImpact;

                List <string> argumentSignatures  = null;
                string        returnTypeSignature = null;
                if (instruction.OpCode.FlowControl == JavaFlowControl.Call)
                {
                    IConstantMemberReference memberReference = (IConstantMemberReference)constantPool[instruction.Operands.ConstantPoolIndex - 1];
                    ConstantNameAndType      nameAndType     = (ConstantNameAndType)constantPool[memberReference.NameAndTypeIndex - 1];
                    ConstantUtf8             descriptor      = (ConstantUtf8)constantPool[nameAndType.DescriptorIndex - 1];
                    string signature = descriptor.Value;
                    SignatureHelper.ParseMethodSignature(signature, out argumentSignatures, out returnTypeSignature);
                }

                switch (instruction.OpCode.StackBehaviorPop)
                {
                case JavaStackBehavior.Pop0:
                    netImpact = 0;
                    break;

                case JavaStackBehavior.Pop1:
                case JavaStackBehavior.PopI:
                case JavaStackBehavior.PopI8:
                case JavaStackBehavior.PopR4:
                case JavaStackBehavior.PopR8:
                case JavaStackBehavior.PopRef:
                    netImpact = -1;
                    break;

                case JavaStackBehavior.Pop1_Pop1:
                case JavaStackBehavior.PopI_PopI:
                case JavaStackBehavior.PopI8_PopI8:
                case JavaStackBehavior.PopI8_PopI:
                case JavaStackBehavior.PopR4_PopR4:
                case JavaStackBehavior.PopR8_PopR8:
                case JavaStackBehavior.PopRef_Pop1:
                case JavaStackBehavior.PopRef_PopI:
                    netImpact = -2;
                    break;

                case JavaStackBehavior.PopRef_PopI_PopI:
                case JavaStackBehavior.PopRef_PopI_PopI8:
                case JavaStackBehavior.PopRef_PopI_PopR4:
                case JavaStackBehavior.PopRef_PopI_PopR8:
                case JavaStackBehavior.PopRef_PopI_PopRef:
                case JavaStackBehavior.PopRef_PopRef:
                    netImpact = -3;
                    break;

                case JavaStackBehavior.PopVar:
                    switch (instruction.OpCode.OpCode)
                    {
                    case JavaOpCodeTag.Dup_x2:
                    case JavaOpCodeTag.Dup2:
                    case JavaOpCodeTag.Dup2_x1:
                    case JavaOpCodeTag.Dup2_x2:
                        netImpact = 1;
                        break;

                    case JavaOpCodeTag.Invokestatic:
                        netImpact = -argumentSignatures.Count;
                        if (returnTypeSignature != "V")
                        {
                            netImpact++;
                        }
                        break;

                    case JavaOpCodeTag.Invokeinterface:
                    case JavaOpCodeTag.Invokespecial:
                    case JavaOpCodeTag.Invokevirtual:
                        netImpact = -argumentSignatures.Count - 1;
                        if (returnTypeSignature != "V")
                        {
                            netImpact++;
                        }
                        break;

                    case JavaOpCodeTag.Multianewarray:
                        netImpact = -instruction.Operands.Dimensions;
                        break;

                    default:
                        throw new FormatException();
                    }

                    break;

                default:
                    throw new FormatException();
                }

                switch (instruction.OpCode.StackBehaviorPush)
                {
                case JavaStackBehavior.Push0:
                    break;

                case JavaStackBehavior.Push1:
                case JavaStackBehavior.PushI:
                case JavaStackBehavior.PushI8:
                case JavaStackBehavior.PushR4:
                case JavaStackBehavior.PushR8:
                case JavaStackBehavior.PushRef:
                case JavaStackBehavior.PushRet:
                    netImpact++;
                    break;

                case JavaStackBehavior.Push1_Push1:
                    netImpact += 2;
                    break;

                case JavaStackBehavior.PushVar:
                    // these are all handled in the pop section
                    break;

                default:
                    throw new FormatException();
                }

                switch (instruction.OpCode.FlowControl)
                {
                case JavaFlowControl.Next:
                case JavaFlowControl.Break:
                case JavaFlowControl.Call:
                case JavaFlowControl.ConditionalBranch:
                case JavaFlowControl.Special:
                    if (!depths[index + 1].HasValue)
                    {
                        depths[index + 1] = depths[index] + netImpact;
                        workQueue.Enqueue(index + 1);
                    }

                    if (instruction.OpCode.FlowControl == JavaFlowControl.ConditionalBranch)
                    {
                        goto case JavaFlowControl.Branch;
                    }

                    break;

                case JavaFlowControl.Branch:
                    switch (instruction.OpCode.OpCode)
                    {
                    case JavaOpCodeTag.Lookupswitch:
                    {
                        LookupSwitchData switchData = (LookupSwitchData)disassembledMethod.SwitchData[instruction.Operands.SwitchDataIndex];
                        foreach (var pair in switchData.Pairs)
                        {
                            int nextIndex = disassembledMethod.Instructions.FindIndex(i => i.Offset == instruction.Offset + pair.Value);
                            if (!depths[nextIndex].HasValue)
                            {
                                depths[nextIndex] = depths[index] + netImpact;
                                workQueue.Enqueue(nextIndex);
                            }
                        }

                        break;
                    }

                    case JavaOpCodeTag.Tableswitch:
                    {
                        TableSwitchData switchData = (TableSwitchData)disassembledMethod.SwitchData[instruction.Operands.SwitchDataIndex];
                        foreach (var offset in switchData.Offsets)
                        {
                            int nextIndex = disassembledMethod.Instructions.FindIndex(i => i.Offset == instruction.Offset + offset);
                            if (!depths[nextIndex].HasValue)
                            {
                                depths[nextIndex] = depths[index] + netImpact;
                                workQueue.Enqueue(nextIndex);
                            }
                        }

                        break;
                    }

                    default:
                    {
                        // single branch target
                        int nextIndex = disassembledMethod.Instructions.FindIndex(i => i.Offset == instruction.Offset + instruction.Operands.BranchTarget);
                        if (!depths[nextIndex].HasValue)
                        {
                            depths[nextIndex] = depths[index] + netImpact;
                            workQueue.Enqueue(nextIndex);
                        }

                        break;
                    }
                    }

                    break;

                case JavaFlowControl.Return:
                    // no work in this method following this instruction
                    break;

                case JavaFlowControl.Throw:
                    // 'catch' blocks are handled separately
                    break;

                case JavaFlowControl.Meta:
                    throw new NotImplementedException();

                default:
                    throw new FormatException();
                }
            }

            return(new ImmutableList <int?>(depths));
        }
예제 #3
0
 public void AddConstantNameAndType(ConstantNameAndType constantNameAndType)
 {
     constantNameAndTypes.Add(constantNameAndType);
     router.Add(constantNameAndTypes.Count);
 }