Example #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);
        }
        internal static AttributeInfo FromMemory(IList <ConstantPoolEntry> constantPool, IntPtr ptr, int offset)
        {
            Contract.Requires <ArgumentNullException>(constantPool != null, "constantPool");
            Contract.Ensures(Contract.Result <AttributeInfo>() != null);

            ushort attributeNameIndex = ConstantPoolEntry.ByteSwap((ushort)Marshal.ReadInt16(ptr, offset));
            uint   attributeLength    = ConstantPoolEntry.ByteSwap((uint)Marshal.ReadInt32(ptr, offset + sizeof(ushort)));

            byte[] info = new byte[attributeLength];
            Marshal.Copy(ptr + offset + sizeof(ushort) + sizeof(uint), info, 0, (int)attributeLength);

            ConstantUtf8 entry = (ConstantUtf8)constantPool[attributeNameIndex - 1];

            switch (entry.Value)
            {
            case "Code":
                return(new Code(attributeNameIndex, info));

            default:
                return(new UnknownAttributeInfo(entry.Value, attributeNameIndex, info));
            }
        }
Example #3
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));
        }
 public void AddConstantUtf8(ConstantUtf8 constantUtf8)
 {
     constantUtf8s.Add(constantUtf8);
     router.Add(constantUtf8s.Count);
 }