예제 #1
0
            public override void Write(JavaWriter wtr)
            {
                Write(wtr, tag, sizeof(ushort));
                ushort constantIndex;

                if (value is int intValue)
                {
                    constantIndex = wtr.ConstInteger(intValue);
                }
                else if (value is float floatValue)
                {
                    constantIndex = wtr.ConstFloat(floatValue);
                }
                else if (value is long longValue)
                {
                    constantIndex = wtr.ConstLong(longValue);
                }
                else if (value is double doubleValue)
                {
                    constantIndex = wtr.ConstDouble(doubleValue);
                }
                else if (value is string stringValue)
                {
                    constantIndex = wtr.ConstString(stringValue);
                }
                else
                {
                    throw wtr.Where.Exception($"invalid constant value");
                }
                wtr.Write16(constantIndex);
            }
예제 #2
0
        bool FillInstruction_Jump(JavaWriter wtr, Instruction inst, byte op, int offset)
        {
            if (inst.Data is ushort && op < 0xC8) // insts with 2-byte offsets
            {
                inst.Bytes    = new byte[3];
                inst.Bytes[0] = op;
            }

            else if (inst.Data is ushort && op == 0xC8)
            {
                inst.Bytes    = new byte[5];
                inst.Bytes[0] = op;
            }

            else if (inst.Data is int[] words && op >= 0xAA && op <= 0xAB)
            {
                int n = words.Length;
                if (n > 16384 ||
                    (op == 0xAA && (n <= 3 || n != 3 + words[2] - words[1] + 1)) ||
                    (op == 0xAB && (n <= 2 || n != 2 + words[1] * 2)))
                {
                    throw wtr.Where.Exception("invalid data in switch instruction");
                }
                inst.Bytes    = new byte[4 - (offset & 3) + n * 4];
                inst.Bytes[0] = op;
            }
예제 #3
0
            public override void Write(JavaWriter wtr)
            {
                wtr.Where.Push(tag);
                wtr.Write16(wtr.ConstUtf8(tag));
                wtr.Fork();
                wtr.Write16(maxStack);
                wtr.Write16(maxLocals);
                wtr.Write32((uint)code.Length);
                wtr.WriteBlock(code);

                if (exceptions == null)
                {
                    wtr.Write16(0);
                }
                else
                {
                    wtr.Write16(exceptions.Length);
                    for (int i = 0; i < exceptions.Length; i++)
                    {
                        wtr.Write16(exceptions[i].start);
                        wtr.Write16(exceptions[i].endPlus1);
                        wtr.Write16(exceptions[i].handler);
                        wtr.Write16((exceptions[i].catchType == null) ? 0 :
                                    wtr.ConstClass(exceptions[i].catchType));
                    }
                }

                attributes.Write(wtr);
                wtr.Join();
                wtr.Where.Pop();
            }
예제 #4
0
        internal JavaConstant.MethodHandle ToConstant(JavaWriter wtr)
        {
            int referenceIndex = -1;

            if (Kind <= HandleKind.PutStatic)
            {
                referenceIndex = wtr.ConstField(Class, Field);
            }
            else if (Kind <= HandleKind.NewInvokeSpecial)
            {
                if (IsInterfaceMethod)
                {
                    referenceIndex = wtr.ConstInterfaceMethod(Class, Method);
                }
                else
                {
                    referenceIndex = wtr.ConstMethod(Class, Method);
                }
            }
            else if (Kind == HandleKind.InvokeInterface && IsInterfaceMethod)
            {
                referenceIndex = wtr.ConstInterfaceMethod(Class, Method);
            }

            if (referenceIndex == -1)
            {
                throw wtr.Where.Exception("invalid method handle");
            }

            return(new JavaConstant.MethodHandle((byte)Kind, (ushort)referenceIndex));
        }
예제 #5
0
        int FillInstructions(JavaWriter wtr)
        {
            int codeLength = 0;

            foreach (var inst in Instructions)
            {
                if (inst.Bytes != null)
                {
                    codeLength += inst.Bytes.Length;
                    continue;
                }

                byte op   = inst.Opcode;
                byte kind = instOperandType[op];
                bool ok;

                wtr.Where.Push($"opcode 0x{op:X2} label 0x{inst.Label:X4}");

                if ((kind & 0x80) != 0)
                {
                    ok = FillInstruction_Const(wtr, inst, op);
                }

                else if ((kind & 0x40) != 0)
                {
                    ok = FillInstruction_Jump(wtr, inst, op, codeLength);
                }

                else if ((kind & 0x10) != 0)
                {
                    ok = FillInstruction_Local(wtr, inst, op);
                }

                else
                {
                    ok = FillInstruction_Special(wtr, inst, op);
                }

                if (!ok)
                {
                    throw wtr.Where.Exception($"unsupported instruction {op:X2} (or operand) at offset {codeLength:X4} (line {inst.Line})");
                }

                if (inst.Bytes != null)
                {
                    codeLength += inst.Bytes.Length;
                }
                else
                {
                    codeLength++;
                }

                wtr.Where.Pop();
            }

            return(codeLength);
        }
예제 #6
0
            public override void Write(JavaWriter wtr)
            {
                wtr.Write16(wtr.ConstUtf8(tag));
                wtr.Fork();
                wtr.Write16(frames.Length);

                for (int i = 0; i < frames.Length; i++)
                {
                    byte type = frames[i].type;
                    wtr.Write8(type);
                    if (type >= 247)
                    {
                        wtr.Write16(frames[i].deltaOffset);
                    }

                    var locals = frames[i].locals;
                    if (locals == null)
                    {
                        wtr.Write16(0);
                    }
                    else
                    {
                        wtr.Write16(locals.Length);
                        for (int j = 0; j < locals.Length; j++)
                        {
                            byte localType = locals[j].type;
                            wtr.Write8(localType);
                            if (localType >= 7 && localType <= 8)
                            {
                                wtr.Write16(locals[j].extra);
                            }
                        }
                    }

                    var stack = frames[i].stack;
                    if (stack == null)
                    {
                        wtr.Write16(0);
                    }
                    else
                    {
                        wtr.Write16(stack.Length);
                        for (int j = 0; j < stack.Length; j++)
                        {
                            byte stackType = stack[j].type;
                            wtr.Write8(stackType);
                            if (stackType >= 7 && stackType <= 8)
                            {
                                wtr.Write16(stack[j].extra);
                            }
                        }
                    }
                }

                wtr.Join();
            }
예제 #7
0
 public void Write(JavaWriter wtr)
 {
     wtr.Write16(set.Count);
     foreach (var attr in set)
     {
         wtr.Where.Push($"attribute '{attr.GetType().Name}'");
         attr.Write(wtr);
         wtr.Where.Pop();
     }
 }
예제 #8
0
        bool FillInstruction_Special(JavaWriter wtr, Instruction inst, byte op)
        {
            if (op == 0xBC)
            {
                inst.Bytes    = new byte[2];
                inst.Bytes[0] = op;
                inst.Bytes[1] = (byte)inst.Data;
            }

            return(true);
        }
예제 #9
0
            public override void Write(JavaWriter wtr)
            {
                var blk = BitConverter.GetBytes(value);

                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(blk);
                }
                wtr.Write8(tag);
                wtr.WriteBlock(blk);
            }
예제 #10
0
        public void Write(JavaWriter wtr)
        {
            int n = pool.Count;

            wtr.Write16((ushort)n);
            for (int i = 1; i < n; i++)
            {
                pool[i]?.Write(wtr);
            }
            editable = false;
        }
예제 #11
0
            public override void Write(JavaWriter wtr)
            {
                int numLines = lines.Length;

                Write(wtr, tag, sizeof(ushort) * (1 + 2 * numLines));
                wtr.Write16(numLines);
                for (int i = 0; i < numLines; i++)
                {
                    wtr.Write16(lines[i].offset);
                    wtr.Write16(lines[i].lineNumber);
                }
            }
예제 #12
0
            public override void Write(JavaWriter wtr)
            {
                int length = sizeof(ushort) // classes.Length
                             + classes.Length * sizeof(ushort);

                Write(wtr, tag, length);
                wtr.Write16(classes.Length);
                for (int i = 0; i < classes.Length; i++)
                {
                    wtr.Write16(wtr.ConstClass(classes[i]));
                }
            }
예제 #13
0
            public override void Write(JavaWriter wtr)
            {
                int length = sizeof(ushort) // number of entries
                             + vars.Length * sizeof(ushort) * 5;

                Write(wtr, tag, length);
                wtr.Write16(vars.Length);
                for (int i = 0; i < vars.Length; i++)
                {
                    wtr.Write16(vars[i].offset);
                    wtr.Write16(vars[i].length);
                    wtr.Write16(wtr.ConstUtf8(vars[i].nameAndType.Name));
                    wtr.Write16(wtr.ConstUtf8(vars[i].nameAndType.Type.ToDescriptor()));
                    wtr.Write16(vars[i].index);
                }
            }
예제 #14
0
            public override void Write(JavaWriter wtr)
            {
                int length = sizeof(ushort) // classes.Length
                             + classes.Length * sizeof(ushort) * 4;

                Write(wtr, tag, length);
                wtr.Write16(classes.Length);
                for (int i = 0; i < classes.Length; i++)
                {
                    wtr.Write16(wtr.ConstClass(classes[i].InnerLongName));
                    ushort v = (classes[i].OuterLongName == null) ? (ushort)0
                             : wtr.ConstClass(classes[i].OuterLongName);
                    wtr.Write16(v);
                    v = (classes[i].InnerShortName == null) ? (ushort)0
                      : wtr.ConstUtf8(classes[i].InnerShortName);
                    wtr.Write16(v);
                    wtr.Write16((ushort)classes[i].Flags);
                }
            }
예제 #15
0
        /*
         * JavaFieldWriter
         */



        public void Write(JavaWriter wtr)
        {
            wtr.Where.Push($"field '{Name}'");

            wtr.Write16((ushort)Flags);
            wtr.Write16(wtr.ConstUtf8(Name));
            wtr.Write16(wtr.ConstUtf8(Type.ToDescriptor()));

            if (Constant != null)
            {
                var attributes = new JavaAttributeSet();
                attributes.Put(new JavaAttribute.ConstantValue(Constant));
                attributes.Write(wtr);
            }
            else
            {
                wtr.Write16(0); // attributes
            }
            wtr.Where.Pop();
        }
예제 #16
0
        public void Write(JavaWriter wtr)
        {
            wtr.Where.Push($"method '{Name}'");

            wtr.Write16((ushort)Flags);
            wtr.Write16(wtr.ConstUtf8(Name));
            wtr.Write16(wtr.ConstUtf8(ToDescriptor()));

            var attributes = new JavaAttributeSet();

            if (Code != null)
            {
                var codeAttr = new JavaAttribute.Code();
                Code.Write(wtr, codeAttr);
                attributes.Put(codeAttr);
            }

            attributes.Write(wtr);

            wtr.Where.Pop();
        }
예제 #17
0
        public void Write(JavaWriter wtr, JavaAttribute.Code codeAttr)
        {
            wtr.Where.Push("method body");

            int codeLength = FillInstructions(wtr);

            if (codeLength > 0xFFFE)
            {
                throw wtr.Where.Exception("output method is too large");
            }

            var labelToOffsetMap = FillJumpTargets(wtr);

            codeAttr.code = new byte[codeLength];
            FillCodeAttr(codeAttr.code);

            codeAttr.maxStack  = (ushort)MaxStack;
            codeAttr.maxLocals = (ushort)MaxLocals;

            WriteExceptionData(codeAttr, labelToOffsetMap);

            if (StackMap != null)
            {
                var attr = StackMap.ToAttribute(wtr, labelToOffsetMap);
                if (attr != null)
                {
                    codeAttr.attributes.Put(attr);
                }
            }

            if (DebugLocals != null)
            {
                var attr = new JavaAttribute.LocalVariableTable(DebugLocals, codeLength);
                codeAttr.attributes.Put(attr);
            }

            FillLineNumbers(codeAttr);

            wtr.Where.Pop();
        }
예제 #18
0
        void FillInstruction_LocalIncrement(JavaWriter wtr, Instruction inst, byte op)
        {
            ushort var = (ushort)((uint)inst.Data & 0xFFFF);
            ushort inc = (ushort)((uint)inst.Data >> 16);

            if (var <= 255 && inc <= 255)
            {
                inst.Bytes    = new byte[3];
                inst.Bytes[0] = op;
                inst.Bytes[1] = (byte)var;
                inst.Bytes[2] = (byte)inc;
            }
            else
            {
                inst.Bytes    = new byte[5];
                inst.Bytes[0] = op;
                inst.Bytes[1] = (byte)(var >> 8);
                inst.Bytes[2] = (byte)var;
                inst.Bytes[3] = (byte)(inc >> 8);
                inst.Bytes[4] = (byte)inc;
            }
        }
예제 #19
0
 public override void Write(JavaWriter wtr)
 {
     wtr.Write8(tag);
     wtr.Write8(referenceKind);
     wtr.Write16(referenceIndex);
 }
예제 #20
0
 public void Write(JavaWriter wtr, byte tag)
 {
     wtr.Write8(tag);
     wtr.Write16(classIndex);
     wtr.Write16(nameAndTypeIndex);
 }
예제 #21
0
 public override void Write(JavaWriter wtr)
 {
     base.Write(wtr, tag);
 }
예제 #22
0
        void FillInstruction_ConstLoad(JavaWriter wtr, Instruction inst)
        {
            int  constantIndex = -1;
            byte op            = 0;

            if (inst.Data is long vLong)
            {
                if (FillInstruction_ConstLoad_Long(inst, vLong))
                {
                    return;
                }
                constantIndex = wtr.ConstLong(vLong);
                op            = 0x14;
            }

            else if (inst.Data is double vDouble)
            {
                if (FillInstruction_ConstLoad_Double(inst, vDouble))
                {
                    return;
                }
                constantIndex = wtr.ConstDouble(vDouble);
                op            = 0x14;
            }

            else
            {
                if (inst.Class != null)
                {
                    if (inst.Data is JavaFieldRef vField)
                    {
                        constantIndex = wtr.ConstField(inst.Class, vField);
                    }

                    else if (inst.Data is JavaMethodRef vMethod)
                    {
                        constantIndex = wtr.ConstMethod(inst.Class, vMethod);
                    }

                    else if (inst.Data == null)
                    {
                        constantIndex = wtr.ConstClass(inst.Class);
                    }
                }

                else if (inst.Data is int vInteger)
                {
                    if (FillInstruction_ConstLoad_Integer(inst, vInteger))
                    {
                        return;
                    }
                    constantIndex = wtr.ConstInteger(vInteger);
                }

                else if (inst.Data is float vFloat)
                {
                    if (FillInstruction_ConstLoad_Float(inst, vFloat))
                    {
                        return;
                    }
                    constantIndex = wtr.ConstFloat(vFloat);
                }

                else if (inst.Data is string vString)
                {
                    constantIndex = wtr.ConstString(vString);
                }

                op          = (byte)((constantIndex <= 255) ? 0x12 : 0x13);
                inst.Opcode = op;
            }

            if (constantIndex == -1)
            {
                throw wtr.Where.Exception("invalid constant in ldc/ldc_w/ldc2_w instruction");
            }

            if (op == 0x12)
            {
                inst.Bytes    = new byte[2];
                inst.Bytes[1] = (byte)constantIndex;
            }
            else
            {
                inst.Bytes    = new byte[3];
                inst.Bytes[1] = (byte)(constantIndex >> 8);
                inst.Bytes[2] = (byte)constantIndex;
            }
            inst.Bytes[0] = op;
        }
예제 #23
0
        bool FillInstruction_Local(JavaWriter wtr, Instruction inst, byte op)
        {
            if (op == 0x84)
            {
                FillInstruction_LocalIncrement(wtr, inst, op);
                return(true);
            }

            ushort var = (ushort)(int)inst.Data;

            if (var <= 3 && op != 0xA9)         // if not 'ret' and small var
            {
                if (op == 0x15)                 // iload
                {
                    inst.Opcode = (byte)(0x1A + var);
                }

                else if (op == 0x16)            // lload
                {
                    inst.Opcode = (byte)(0x1E + var);
                }

                else if (op == 0x17)            // fload
                {
                    inst.Opcode = (byte)(0x22 + var);
                }

                else if (op == 0x18)            // dload
                {
                    inst.Opcode = (byte)(0x26 + var);
                }

                else if (op == 0x19)            // aload
                {
                    inst.Opcode = (byte)(0x2A + var);
                }

                else if (op == 0x36)            // istore
                {
                    inst.Opcode = (byte)(0x3B + var);
                }

                else if (op == 0x37)            // lstore
                {
                    inst.Opcode = (byte)(0x3F + var);
                }

                else if (op == 0x38)            // fstore
                {
                    inst.Opcode = (byte)(0x43 + var);
                }

                else if (op == 0x39)            // dstore
                {
                    inst.Opcode = (byte)(0x47 + var);
                }

                else if (op == 0x3A)            // astore
                {
                    inst.Opcode = (byte)(0x4B + var);
                }

                else
                {
                    return(false);
                }
            }

            else if (var <= 255)
            {
                inst.Bytes    = new byte[2];
                inst.Bytes[0] = op;
                inst.Bytes[1] = (byte)var;
            }

            else
            {
                inst.Bytes    = new byte[4];
                inst.Bytes[0] = 0xC4; // wide
                inst.Bytes[1] = op;
                inst.Bytes[2] = (byte)(var >> 8);
                inst.Bytes[3] = (byte)var;
            }

            return(true);
        }
예제 #24
0
        public void Write(JavaWriter wtr)
        {
            wtr.Where.Push($"writing class '{Name}'");

            if (Name == null)
            {
                throw wtr.Where.Exception("missing class name");
            }

            wtr.Write16((ushort)Flags);
            wtr.Write16(wtr.ConstClass(Name));
            wtr.Write16(wtr.ConstClass(Super));

            if (Interfaces == null)
            {
                wtr.Write16(0);
            }
            else
            {
                wtr.Write16(Interfaces.Count);
                for (int i = 0; i < Interfaces.Count; i++)
                {
                    wtr.Write16(wtr.ConstClass(Interfaces[i]));
                }
            }

            if (Fields == null)
            {
                wtr.Write16(0);
            }
            else
            {
                wtr.Write16(Fields.Count);
                for (int i = 0; i < Fields.Count; i++)
                {
                    Fields[i].Write(wtr);
                }
            }

            if (Methods == null)
            {
                wtr.Write16(0);
            }
            else
            {
                wtr.Write16(Methods.Count);
                for (int i = 0; i < Methods.Count; i++)
                {
                    Methods[i].Write(wtr);
                }
            }

            var attributes = new JavaAttributeSet();

            if (SourceFile != null)
            {
                attributes.Put(new JavaAttribute.SourceFile(SourceFile));
            }

            if (Signature != null)
            {
                attributes.Put(new JavaAttribute.Signature(Signature));
            }

            WriteInnerClasses(attributes);

            if (wtr.bootstrapMethods != null)
            {
                attributes.Put(wtr.bootstrapMethods);
            }

            attributes.Write(wtr);

            wtr.Where.Pop();
        }
예제 #25
0
        bool FillInstruction_Const(JavaWriter wtr, Instruction inst, byte op)
        {
            int length = 3;
            int count  = 0;

            if (op >= 0x12 && op <= 0x14)
            {
                FillInstruction_ConstLoad(wtr, inst);
                return(true);
            }

            int constantIndex = -1;

            if (op >= 0xB2 && op <= 0xB5)
            {
                // getstatic/putstatic/getfield/putfield
                if (inst.Data is JavaFieldRef vField)
                {
                    constantIndex = wtr.ConstField(inst.Class, vField);
                }
            }

            else if (op >= 0xB6 && op <= 0xB8)
            {
                // invokevirtual/invokespecial/invokestatic
                if (inst.Data is JavaMethodRef vMethod)
                {
                    constantIndex = wtr.ConstMethod(inst.Class, vMethod);
                }
            }

            else if (op == 0xB9)
            {
                // invokeinterface
                if (inst.Data is JavaMethodRef vMethod)
                {
                    constantIndex = wtr.ConstInterfaceMethod(inst.Class, vMethod);
                    length        = 5;
                    count         = 1; // 'this' argument
                    int numArgs = vMethod.Parameters.Count;
                    for (int i = 0; i < numArgs; i++)
                    {
                        count += vMethod.Parameters[i].Type.Category;
                    }
                }
            }

            else if (op == 0xBA)
            {
                // invokedynamic
                if (inst.Data is JavaCallSite vCallSite)
                {
                    constantIndex = wtr.ConstInvokeDynamic(vCallSite);
                    length        = 5;
                }
            }

            else if (op >= 0xBB)
            {
                // new/anewarray/checkcast/instanceof/multianewarray
                constantIndex = wtr.ConstClass(inst.Class);

                if (op == 0xC5)
                {
                    length++;
                    count = (int)inst.Data;
                }
            }

            if (constantIndex == -1)
            {
                return(false);
            }

            inst.Bytes    = new byte[length];
            inst.Bytes[0] = op;
            inst.Bytes[1] = (byte)(constantIndex >> 8);
            inst.Bytes[2] = (byte)constantIndex;

            if (op == 0xB9 || op == 0xC5)
            {
                inst.Bytes[3] = (byte)count;
            }

            return(true);
        }
예제 #26
0
 public abstract void Write(JavaWriter wrt);
예제 #27
0
 public override void Write(JavaWriter wtr)
 {
     wtr.Write8(tag);
     wtr.Write32((uint)value);
 }
예제 #28
0
 public override void Write(JavaWriter wtr)
 {
     wtr.Write8(tag);
     wtr.Write16(bootstrapMethodIndex);
     wtr.Write16(nameAndTypeIndex);
 }
예제 #29
0
 public override void Write(JavaWriter wtr)
 {
     wtr.Write8(tag);
     wtr.Write16(descriptorIndex);
 }
예제 #30
0
 public override void Write(JavaWriter wtr)
 {
     wtr.Write8(tag);
     wtr.WriteString(str);
 }