Esempio n. 1
0
 public Exceptions(JavaReader rdr)
 {
     classes = new JavaType[rdr.Read16()];
     for (int i = 0; i < classes.Length; i++)
     {
         classes[i] = rdr.ConstClass(rdr.Read16());
     }
 }
Esempio n. 2
0
 public InnerClasses(JavaReader rdr)
 {
     classes = new JavaClass.InnerClass[rdr.Read16()];
     for (int i = 0; i < classes.Length; i++)
     {
         classes[i] = new JavaClass.InnerClass();
         classes[i].InnerLongName = rdr.ConstClass(rdr.Read16()).ClassName;
         ushort v = rdr.Read16();
         if (v != 0)
         {
             classes[i].OuterLongName = rdr.ConstClass(v).ClassName;
         }
         v = rdr.Read16();
         if (v != 0)
         {
             classes[i].InnerShortName = rdr.ConstUtf8(v);
         }
         classes[i].Flags = (JavaAccessFlags)rdr.Read16();
     }
 }
Esempio n. 3
0
            public Code(JavaReader rdr)
            {
                rdr.Where.Push(tag);
                (maxStack, maxLocals) = (rdr.Read16(), rdr.Read16());
                var codeLength = ReadLength(rdr, "code");

                code = rdr.ReadBlock(codeLength);

                exceptions = new Exception[rdr.Read16()];
                for (int i = 0; i < exceptions.Length; i++)
                {
                    exceptions[i].start    = rdr.Read16();
                    exceptions[i].endPlus1 = rdr.Read16();
                    exceptions[i].handler  = rdr.Read16();
                    ushort catchType = rdr.Read16();
                    exceptions[i].catchType =
                        (catchType == 0 ? null : rdr.ConstClass(catchType).ClassName);
                }

                attributes = new JavaAttributeSet(rdr);
                rdr.Where.Pop();
            }
Esempio n. 4
0
        public JavaCode(JavaReader rdr, JavaMethod method, JavaAttribute.Code codeAttr)
        {
            rdr.Where.Push("method body");

            Method    = method;
            MaxStack  = codeAttr.maxStack;
            MaxLocals = codeAttr.maxLocals;
            var codeText = codeAttr.code;

            Instructions = new List <Instruction>();

            int offset = 0;

            while (offset < codeText.Length)
            {
                var  inst    = new Instruction();
                var  offset0 = offset;
                byte op      = codeText[offset++];
                byte kind;

                if (op == 0xC4)
                {
                    // wide prefix doubles operand size
                    op   = codeText[offset++];
                    kind = instOperandType[op];
                    if ((kind & 0x10) != 0x10)
                    {
                        throw rdr.Where.Exception($"invalid use of wide opcode prefix at {(offset - 2).ToString("X4")}");
                    }
                    kind = (byte)(0x10 | ((kind & 0x0F) << 1));
                    if (op == 0x84)
                    {
                        inst.Data = (uint)((codeText[offset] << 24)
                                           | (codeText[offset + 1] << 16)
                                           | (codeText[offset + 2] << 8)
                                           | codeText[offset + 3]);
                    }
                    else
                    {
                        inst.Data = (short)((codeText[offset] << 8) | codeText[offset + 1]);
                    }
                }
                else if (op == 0xAA || op == 0xAB)
                {
                    offset = ReadSwitch(codeText, op, offset, inst);
                    if (offset == -1)
                    {
                        throw rdr.Where.Exception($"switch opcode {op:X2} not supported at offset {offset0:X4}");
                    }
                    kind = 0;
                }
                else
                {
                    kind = instOperandType[op];

                    if ((kind & 0x80) == 0x80)
                    {
                        // constant reference
                        int constantIndex = codeText[offset];
                        if (kind >= 0x82 && kind <= 0x84)
                        {
                            constantIndex = (constantIndex << 8) | codeText[offset + 1];
                        }

                        var constantType = rdr.ConstType(constantIndex);

                        if (constantType == typeof(JavaConstant.String))
                        {
                            inst.Data = rdr.ConstString(constantIndex);
                        }

                        else if (constantType == typeof(JavaConstant.Integer))
                        {
                            inst.Data = rdr.ConstInteger(constantIndex);
                        }

                        else if (constantType == typeof(JavaConstant.Float))
                        {
                            inst.Data = rdr.ConstFloat(constantIndex);
                        }

                        else if (constantType == typeof(JavaConstant.Long))
                        {
                            inst.Data = rdr.ConstLong(constantIndex);
                        }

                        else if (constantType == typeof(JavaConstant.Double))
                        {
                            inst.Data = rdr.ConstDouble(constantIndex);
                        }

                        else if (constantType == typeof(JavaConstant.Class))
                        {
                            inst.Class = rdr.ConstClass(constantIndex);
                        }

                        else if (constantType == typeof(JavaConstant.FieldRef))
                        {
                            (inst.Class, inst.Data) = rdr.ConstField(constantIndex);
                        }

                        else if (constantType == typeof(JavaConstant.MethodRef))
                        {
                            (inst.Class, inst.Data) = rdr.ConstMethod(constantIndex);
                        }

                        else if (constantType == typeof(JavaConstant.InterfaceMethodRef))
                        {
                            (inst.Class, inst.Data) = rdr.ConstInterfaceMethod(constantIndex);
                        }

                        else if (constantType == typeof(JavaConstant.InvokeDynamic))
                        {
                            var callSite = rdr.ConstInvokeDynamic(constantIndex);
                            inst.Data = callSite;

                            if (rdr.callSites == null)
                            {
                                rdr.callSites = new List <JavaCallSite>();
                            }
                            rdr.callSites.Add(callSite);
                        }

                        else
                        {
                            rdr.Where.Push($"opcode {op:X2} offset {offset0:X4}");
                            throw rdr.Where.Exception((constantType == null)
                                    ? $"bad constant index '{constantIndex}'"
                                    : $"unsupported constant of type '{constantType.Name}'");
                        }
                    }
                    else if ((kind & 0x40) == 0x40)
                    {
                        // control transfer, 32-bit or 16-bit offset

                        /*if ((kind & 0x4F) == 0x44)
                         *  throw rdr.Where.Exception($"32-bit branch offsets not supported at offset {(offset - 2).ToString("X4")}");*/
                        int jumpOffset = ((codeText[offset] << 8) | codeText[offset + 1]);
                        if ((kind & 0x4F) == 0x44)
                        {
                            // 32-bit branch offset in 'goto_w' instruction
                            jumpOffset = (jumpOffset << 8) | codeText[offset + 2];
                            jumpOffset = (jumpOffset << 8) | codeText[offset + 3];
                        }
                        inst.Data = (ushort)(offset0 + jumpOffset);
                    }
                    else if ((kind & 0x30) != 0)
                    {
                        // 0x10 - one or two bytes of immediate data
                        // 0x20 - local variable index
                        if ((kind & 0x0F) == 0x01)
                        {
                            inst.Data = (int)codeText[offset];
                        }
                        else
                        {
                            inst.Data = (int)((codeText[offset] << 8) | codeText[offset + 1]);
                        }
                    }
                    else if (kind != 0)
                    {
                        throw rdr.Where.Exception("unknown opcode");
                    }
                }

                offset += (kind & 0x0F);

                int n = offset - offset0;
                inst.Bytes = new byte[offset - offset0];
                for (int i = 0; i < n; i++)
                {
                    inst.Bytes[i] = codeText[offset0 + i];
                }

                inst.Opcode = op;

                inst.Label = (ushort)offset0;

                Instructions.Add(inst);
            }

            ReadLineNumberTable(codeAttr);

            Exceptions = new List <JavaAttribute.Code.Exception>(codeAttr.exceptions);

            var stackMapAttr = codeAttr.attributes.GetAttr <JavaAttribute.StackMapTable>();

            if (stackMapAttr != null)
            {
                StackMap = new JavaStackMap(stackMapAttr, rdr);
            }

            rdr.Where.Pop();
        }
Esempio n. 5
0
            public BootstrapMethods(JavaReader rdr)
            {
                methods = new Item[rdr.Read16()];
                for (int i = 0; i < methods.Length; i++)
                {
                    methods[i].mh = rdr.ConstMethodHandle(rdr.Read16());
                    var args = new object[rdr.Read16()];
                    for (int j = 0; j < args.Length; j++)
                    {
                        var    constantIndex = rdr.Read16();
                        var    constantType  = rdr.ConstType(constantIndex);
                        object value;

                        if (constantType == typeof(JavaConstant.Integer))
                        {
                            value = rdr.ConstInteger(constantIndex);
                        }

                        else if (constantType == typeof(JavaConstant.Float))
                        {
                            value = rdr.ConstFloat(constantIndex);
                        }

                        else if (constantType == typeof(JavaConstant.Long))
                        {
                            value = rdr.ConstLong(constantIndex);
                        }

                        else if (constantType == typeof(JavaConstant.Double))
                        {
                            value = rdr.ConstDouble(constantIndex);
                        }

                        else if (constantType == typeof(JavaConstant.Class))
                        {
                            value = rdr.ConstClass(constantIndex);
                        }

                        else if (constantType == typeof(JavaConstant.String))
                        {
                            value = rdr.ConstString(constantIndex);
                        }

                        else if (constantType == typeof(JavaConstant.MethodHandle))
                        {
                            value = rdr.ConstMethodHandle(constantIndex);
                        }

                        else if (constantType == typeof(JavaConstant.MethodType))
                        {
                            value = rdr.ConstMethodType(constantIndex);
                        }

                        else
                        {
                            throw rdr.Where.Exception($"invalid bootstrap method argument");
                        }

                        args[j] = value;
                    }
                    methods[i].args = args;
                }
            }
Esempio n. 6
0
            public ushort methodConst;  // partial implementation

            public EnclosingMethod(JavaReader rdr)
            {
                className   = rdr.ConstClass(rdr.Read16()).ClassName;
                methodConst = rdr.Read16();
            }
Esempio n. 7
0
        public JavaClass(JavaReader rdr, int majorVersion, int minorVersion, bool withCode = true)
        {
            rdr.Class = this;

            Flags = (JavaAccessFlags)rdr.Read16();

            Name = rdr.ConstClass(rdr.Read16()).ClassName;

            rdr.Where.Push($"reading class '{Name}' version {majorVersion}.{minorVersion}");

            ushort superConstIndex = rdr.Read16();

            if (!(superConstIndex == 0 && Name == "java.lang.Object"))
            {
                Super = rdr.ConstClass(superConstIndex).ClassName;
            }

            var interfaceCount = rdr.Read16();

            if (interfaceCount != 0)
            {
                Interfaces = new List <string>(interfaceCount);
                for (int i = 0; i < interfaceCount; i++)
                {
                    Interfaces.Add(rdr.ConstClass(rdr.Read16()).ClassName);
                }
            }

            var fieldCount = rdr.Read16();

            if (fieldCount != 0)
            {
                Fields = new List <JavaField>(fieldCount);
                for (int i = 0; i < fieldCount; i++)
                {
                    Fields.Add(new JavaField(rdr));
                }
            }

            var methodCount = rdr.Read16();

            if (methodCount != 0)
            {
                Methods = new List <JavaMethod>(methodCount);
                for (int i = 0; i < methodCount; i++)
                {
                    Methods.Add(new JavaMethod(rdr, withCode));
                }
            }

            var attributes = new JavaAttributeSet(rdr, withCode);

            var sourceAttr = attributes.GetAttr <JavaAttribute.SourceFile>();

            SourceFile = sourceAttr?.fileName;

            var signatureAttr = attributes.GetAttr <JavaAttribute.Signature>();

            Signature = signatureAttr?.descriptor;

            var innerAttr = attributes.GetAttr <JavaAttribute.InnerClasses>();

            if (innerAttr != null)
            {
                var enclosingClass =
                    attributes.GetAttr <JavaAttribute.EnclosingMethod>()
                    ?.className;
                ParseInnerClasses(innerAttr.classes, enclosingClass);
            }

            ReadCallSites(rdr, attributes);

            if ((Flags & JavaAccessFlags.ACC_ENUM) != 0)
            {
                bool superOk = (Super == "java.lang.Enum");
                if (IsInnerClass() && Super == OuterAndInnerClasses[0].OuterLongName)
                {
                    superOk = true;
                }
                if (!superOk)
                {
                    throw rdr.Where.Exception($"bad super class '{Super}' for enum");
                }
            }

            rdr.Where.Pop();
        }