Example #1
0
        private byte[] LinkPass2()
        {
            MemoryStream codeBytesStream = new MemoryStream();
            BinaryWriter codeBytesWriter = new BinaryWriter(codeBytesStream);

            for (int i = 0; i < outputCode.Count; i++)
            {
                JavaInstruction instr = outputCode[i];

                codeBytesWriter.Write((byte)instr.Opcode);

                Java.ByteCode.JavaInstructionDescption descr = Java.ByteCode.JavaInstructions[instr.Opcode];
                int operandSize = descr.Size - 1;

                switch (descr.OpType)
                {
                case Java.ByteCode.JavaOperandType.ConstValue:
                    switch (operandSize)
                    {
                    case 1: codeBytesWriter.Write((sbyte)instr.Operand); break;

                    case 2: codeBytesWriter.WriteBE((short)instr.Operand); break;

                    case 4: codeBytesWriter.WriteBE((int)instr.Operand); break;
                    }
                    break;

                case Java.ByteCode.JavaOperandType.ConstPool:
                    if (operandSize == 1)
                    {
                        codeBytesWriter.Write((byte)((ushort)instr.Operand));
                    }
                    else
                    {
                        codeBytesWriter.WriteBE((ushort)instr.Operand);
                    }
                    break;

                case Java.ByteCode.JavaOperandType.LocalVar:
                    if (instr.Operand is ushort)
                    {
                        codeBytesWriter.WriteBE((ushort)instr.Operand);
                    }
                    else
                    {
                        codeBytesWriter.Write((byte)instr.Operand);
                    }
                    break;

                case Java.ByteCode.JavaOperandType.Offset:
                    if (instr.Operand is string)
                    {
                        codeBytesWriter.WriteBE((short)(outputCodeOffsets[outputCode[labels[(string)instr.Operand]]] - outputCodeOffsets[instr]));
                    }
                    else
                    {
                        codeBytesWriter.WriteBE((short)(outputCodeOffsets[(JavaInstruction)instr.Operand] - outputCodeOffsets[instr]));
                    }
                    break;

                case Java.ByteCode.JavaOperandType.Special:
                    switch (instr.Opcode)
                    {
                    case Java.OpCodes.iinc:
                        if (instr.Operand is int)
                        {
                            codeBytesWriter.WriteBE((int)instr.Operand);
                        }
                        else
                        {
                            codeBytesWriter.WriteBE((short)instr.Operand);
                        }
                        break;

                    case Java.OpCodes.tableswitch:
                        //TODO: Java.OpCodes.tableswitch
                        break;

                    case Java.OpCodes.lookupswitch:
                        LookupswitchOperand lookUpOperand = (LookupswitchOperand)instr.Operand;

                        int padding = (4 - ((outputCodeOffsets[instr] + 1) % 4)) % 4;
                        codeBytesWriter.Write(new byte[padding]);
                        codeBytesWriter.WriteBE(outputCodeOffsets[outputCode[labels[lookUpOperand.DefaultLabel]]] - outputCodeOffsets[instr]);
                        codeBytesWriter.WriteBE(lookUpOperand.Pairs.Length);

                        for (int j = 0; j < lookUpOperand.Pairs.Length; j++)
                        {
                            codeBytesWriter.WriteBE(lookUpOperand.Pairs[j].Item1);
                            codeBytesWriter.WriteBE(outputCodeOffsets[outputCode[labels[lookUpOperand.Pairs[j].Item2]]] - outputCodeOffsets[instr]);
                        }

                        break;

                    case Java.OpCodes.invokeinterface:
                    case Java.OpCodes.invokedynamic:
                        uint op = (uint)instr.Operand;
                        codeBytesWriter.WriteBE((ushort)(op & 0xfff));
                        codeBytesWriter.WriteBE((ushort)(op >> 16));
                        break;

                    case Java.OpCodes.newarray:
                        codeBytesWriter.Write((byte)instr.Operand);
                        break;

                    case Java.OpCodes.wide:
                        break;

                    case Java.OpCodes.multianewarray:
                        int data = (int)instr.Operand;
                        codeBytesWriter.WriteBE((ushort)(data & 0xffff));
                        codeBytesWriter.Write((byte)((data & 0xff0000) >> 16));
                        break;
                    }
                    break;
                }
            }

            byte[] result = codeBytesStream.ToArray();
            codeBytesStream.Close();
            return(result);
        }
Example #2
0
        private void LinkPass1(Java.ConstantPool pool)
        {
            int offset = StartOffset;

            bool lastWide = false;

            for (int i = 0; i < outputCode.Count; i++)
            {
                JavaInstruction instr = outputCode[i];
                outputCodeOffsets.Add(instr, offset);

                object lastOperand = instr.Operand;
                if (instr.Operand is Java.Constant)
                {
                    instr.Operand = pool.AddConstant((Java.Constant)instr.Operand);
                }
                else if (instr.Operand is MultianewarrayOperand)
                {
                    MultianewarrayOperand operand = (MultianewarrayOperand)instr.Operand;
                    instr.Operand = pool.AddConstant(operand.ClassOperand) | (operand.DimensionsOperand << 16);
                }

                if (instr.Opcode == Java.OpCodes.ldc)
                {
                    if (((ushort)instr.Operand) > byte.MaxValue)
                    {
                        instr.Opcode = Java.OpCodes.ldc_w;
                    }
                }

                if (instr.Opcode == Java.OpCodes.invokeinterface)
                {
                    if (lastOperand is Java.Constants.MethodRef)
                    {
                        Java.Constants.MethodRef m = (Java.Constants.MethodRef)lastOperand;

                        lastOperand = new Java.Constants.InterfaceMethodRef(m.Class, m.Name, m.Descriptor);
                    }

                    byte   argsCount  = CalculateInterfaceCallArgsCount(((Java.Constants.InterfaceMethodRef)lastOperand).Descriptor);
                    ushort constIndex = (ushort)instr.Operand;
                    instr.Operand = (uint)(constIndex | ((argsCount + 1) << 24));
                }

                int size = Java.ByteCode.JavaInstructions[instr.Opcode].Size;
                if ((size == -1) && (instr.Opcode == Java.OpCodes.lookupswitch))
                {
                    LookupswitchOperand op = (LookupswitchOperand)lastOperand;
                    instr.Operand = op;

                    int paddingLendth = (4 - ((offset + 1) % 4)) % 4;

                    size = 1                      //opcode
                           + paddingLendth        //padding
                           + 4                    //default
                           + 4                    //npairs
                           + op.Pairs.Length * 8; //pairs count * pairs size (8 = 4 + 4)
                }

                if (lastWide)
                {
                    size     = (size - 1) * 2 + 1;
                    lastWide = false;
                }

                offset += size;

                if (instr.Opcode == Java.OpCodes.wide)
                {
                    lastWide = true;
                }
            }
        }