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 static void Disasm(Attributes.Code codeAttr, ConstantPool pool, CountingStreamWriter writer, string[] sourceFile)
        {
            byte[] code = codeAttr.CodeBytes;

            int  i        = 0;
            bool lastWide = false;

            Attributes.LineNumberTable lnt    = codeAttr.Attributes.Where(A => A is Attributes.LineNumberTable).FirstOrDefault() as Attributes.LineNumberTable;
            Attributes.LineNumberTable newLnt = new Attributes.LineNumberTable();
            int lastLine = 0;

            while (i < code.Length)
            {
                if ((lnt != null) && (sourceFile != null))
                {
                    try
                    {
                        var lns = lnt.Table.Where(ln => ln.StartPC <= i);
                        if (lns.Count() > 0)
                        {
                            int currLine = lns.Aggregate((i1, i2) => i1.StartPC > i2.StartPC ? i1 : i2).LineNumberInFile;

                            if (lastLine != currLine)
                            {
                                writer.WriteLine("              ## {0}", sourceFile[currLine]);
                            }
                            lastLine = currLine;
                        }
                    }
                    catch (Exception)
                    {
                    }
                }

                newLnt.Table.Add(new Attributes.LineNumberTable.LineNumber((ushort)i, (ushort)writer.CurrLine));

                OpCodes op = (OpCodes)code[i];

                if (!lastWide)
                {
                    writer.Write("              {0,4:X} : ", i);
                }

                if (op == OpCodes.wide)
                {
                    writer.Write("wide ");
                    i++;
                    lastWide = true;
                    continue;
                }

                string opStr      = op.ToString();
                string operandStr = "";

                if (opStr[0] == '_')
                {
                    opStr = opStr.Substring(1);
                }

                writer.Write(opStr);

                ByteCode.JavaInstructionDescption descr = ByteCode.JavaInstructions[op];
                int operandSize = descr.Size - 1;

                if (lastWide)
                {
                    operandSize *= 2;
                    lastWide     = false;
                }

                switch (descr.OpType)
                {
                case ByteCode.JavaOperandType.ConstPool:
                    ushort index = (ushort)BitConverterBE.ReadAsInt32(code, i + 1, operandSize);
                    operandStr = pool[index].ToString();
                    break;

                case ByteCode.JavaOperandType.ConstValue:
                case ByteCode.JavaOperandType.LocalVar:
                    operandStr = BitConverterBE.ReadAsInt32(code, i + 1, operandSize).ToString();
                    break;

                case ByteCode.JavaOperandType.Offset:
                    short offset = (short)BitConverterBE.ReadAsInt32(code, i + 1, operandSize);
                    operandStr = String.Format("{0,4:X}", (i + offset));
                    break;

                case ByteCode.JavaOperandType.Special:
                    switch (op)
                    {
                    case OpCodes.iinc:
                        int op1 = BitConverterBE.ReadAsInt32(code, i + 1, operandSize / 2);
                        int op2 = BitConverterBE.ReadAsInt32(code, i + 1 + operandSize / 2, operandSize / 2);
                        operandStr = String.Format("{0}, {1}", op1, op2);
                        break;

                    case OpCodes.lookupswitch:
                        int paddingLength = (4 - ((i + 1) % 4)) % 4;
                        int _default      = BitConverterBE.ReadAsInt32(code, i + paddingLength + 1, 4);
                        int npairs        = BitConverterBE.ReadAsInt32(code, i + paddingLength + 5, 4);
                        int pairsStart    = i + paddingLength + 9;
                        operandSize = npairs * 8 + 8 + paddingLength;

                        writer.WriteLine(" default: {0,4:X}, npairs: {1}", _default, npairs);

                        for (int pair = 0; pair < npairs; pair++)
                        {
                            int pairValue  = BitConverterBE.ReadAsInt32(code, pairsStart + (pair * 8), 4);
                            int pairOffset = BitConverterBE.ReadAsInt32(code, pairsStart + (pair * 8) + 4, 4);

                            writer.WriteLine("                     {0,4:X} : {1}", pairOffset, pairValue);
                        }
                        break;

                    case OpCodes.tableswitch:
                        paddingLength = (4 - ((i + 1) % 4)) % 4;
                        _default      = BitConverterBE.ReadAsInt32(code, i + paddingLength + 1, 4);
                        int low   = BitConverterBE.ReadAsInt32(code, i + paddingLength + 5, 4);
                        int hight = BitConverterBE.ReadAsInt32(code, i + paddingLength + 9, 4);

                        writer.WriteLine(" default: {0,4:X}, low: {1}, hight: {2}", _default, low, hight);
                        int jmpCount = hight - low + 1;
                        int jmpStart = i + paddingLength + 13;
                        operandSize = jmpCount * 4 + 13 + paddingLength;

                        for (int jmp = 0; jmp < jmpCount; jmp++)
                        {
                            writer.WriteLine("                     {0,4:X} : {1}", BitConverterBE.ReadAsInt32(code, jmpStart + jmp * 4, 4), low + jmp);
                        }
                        break;

                    case OpCodes.invokeinterface:
                    case OpCodes.invokedynamic:
                        index      = (ushort)BitConverterBE.ReadAsInt32(code, i + 1, 2);
                        operandStr = pool[index].ToString();
                        break;

                    case OpCodes.newarray:
                        operandStr = ArrayTypes[code[i + 1]];
                        break;

                    case OpCodes.multianewarray:
                        index = (ushort)BitConverterBE.ReadAsInt32(code, i + 1, 2);
                        byte dismensions = code[i + 3];
                        operandStr = String.Format("{0}, {1}", dismensions, pool[index].ToString());
                        break;
                    }
                    ;
                    break;
                }

                writer.WriteLine(" {0}", operandStr);
                i += 1 + operandSize;
            }

            if (Program.DebugBytecode)
            {
                if (lnt != null)
                {
                    codeAttr.Attributes.Remove(lnt);
                }
                codeAttr.Attributes.Add(newLnt);
            }
        }