示例#1
0
            public ConstantValue(JavaReader rdr)
            {
                var constantIndex = rdr.Read16();
                var constantType  = rdr.ConstType(constantIndex);

                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.String))
                {
                    value = rdr.ConstString(constantIndex);
                }

                else
                {
                    throw rdr.Where.Exception($"invalid constant value");
                }
            }
示例#2
0
        /*
         * JavaFieldReader
         */



        public JavaField(JavaReader rdr)
        {
            Class = rdr.Class;

            Flags = (JavaAccessFlags)rdr.Read16();

            Name = rdr.ConstUtf8(rdr.Read16());

            rdr.Where.Push($"field '{Name}'");

            Type = new JavaType(rdr.ConstUtf8(rdr.Read16()), rdr.Where);

            var attributes = new JavaAttributeSet(rdr);

            if ((Flags & JavaAccessFlags.ACC_STATIC) != 0)
            {
                var constAttr = attributes.GetAttr <JavaAttribute.ConstantValue>();
                if (constAttr != null)
                {
                    InitConstant(constAttr.value, rdr.Where);
                }
            }

            rdr.Where.Pop();
        }
示例#3
0
 public Exceptions(JavaReader rdr)
 {
     classes = new JavaType[rdr.Read16()];
     for (int i = 0; i < classes.Length; i++)
     {
         classes[i] = rdr.ConstClass(rdr.Read16());
     }
 }
示例#4
0
 public LineNumberTable(JavaReader rdr)
 {
     lines = new Item[rdr.Read16()];
     for (int i = 0; i < lines.Length; i++)
     {
         lines[i].offset     = rdr.Read16();
         lines[i].lineNumber = rdr.Read16();
     }
 }
示例#5
0
 public MethodParameters(JavaReader rdr)
 {
     parms = new Item[rdr.Read8()];
     for (int i = 0; i < parms.Length; i++)
     {
         parms[i].name  = rdr.ConstUtf8(rdr.Read16());
         parms[i].flags = rdr.Read16();
     }
 }
示例#6
0
            public StackMapTable(JavaReader rdr)
            {
                frames = new Item[rdr.Read16()];
                for (int i = 0; i < frames.Length; i++)
                {
                    byte type = rdr.Read8();
                    frames[i].type = type;
                    if (type >= 247)
                    {
                        frames[i].deltaOffset = rdr.Read16();
                    }
                    else if (type <= 127)
                    {
                        if (type < 64)
                        {
                            frames[i].deltaOffset = type;
                        }
                        else
                        {
                            frames[i].deltaOffset = (ushort)(type - 64);
                        }
                    }

                    if (type >= 252)
                    {
                        int numLocals = (type == 255) ? rdr.Read16() : (type - 251);
                        var locals    = new Slot[numLocals];
                        for (int j = 0; j < numLocals; j++)
                        {
                            byte localType = rdr.Read8();
                            locals[j].type = localType;
                            if (localType >= 7 && localType <= 8)
                            {
                                locals[j].extra = rdr.Read16();
                            }
                        }
                        frames[i].locals = locals;
                    }

                    if ((type >= 64 && type <= 127) || type == 247 || type == 255)
                    {
                        int numStack = (type == 255) ? rdr.Read16() : 1;
                        var stack    = new Slot[numStack];
                        for (int j = 0; j < numStack; j++)
                        {
                            byte stackType = rdr.Read8();
                            stack[j].type = stackType;
                            if (stackType >= 7 && stackType <= 8)
                            {
                                stack[j].extra = rdr.Read16();
                            }
                        }
                        frames[i].stack = stack;
                    }
                }
            }
示例#7
0
        public static int ReadLength(JavaReader rdr, string name)
        {
            var length = rdr.Read32();

            if (length >= int.MaxValue)
            {
                throw rdr.Where.Exception($"{name} attribute too large");
            }
            return((int)length);
        }
示例#8
0
            public Double(JavaReader rdr)
            {
                var blk = rdr.ReadBlock(8);

                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(blk);
                }
                value = BitConverter.ToDouble(blk, 0);
            }
示例#9
0
            public Float(JavaReader rdr)
            {
                var blk = rdr.ReadBlock(4);

                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(blk);
                }
                value = BitConverter.ToSingle(blk, 0);
            }
示例#10
0
        JavaConstant ReadConstant(JavaReader rdr)
        {
            var tag = rdr.Read8();

            switch (tag)
            {
            case JavaConstant.Utf8.tag:
                return(new JavaConstant.Utf8(rdr));

            case JavaConstant.Integer.tag:
                return(new JavaConstant.Integer(rdr));

            case JavaConstant.Float.tag:
                return(new JavaConstant.Float(rdr));

            case JavaConstant.Long.tag:
                return(new JavaConstant.Long(rdr));

            case JavaConstant.Double.tag:
                return(new JavaConstant.Double(rdr));

            case JavaConstant.Class.tag:
                return(new JavaConstant.Class(rdr));

            case JavaConstant.String.tag:
                return(new JavaConstant.String(rdr));

            case JavaConstant.FieldRef.tag:
                return(new JavaConstant.FieldRef(rdr));

            case JavaConstant.MethodRef.tag:
                return(new JavaConstant.MethodRef(rdr));

            case JavaConstant.InterfaceMethodRef.tag:
                return(new JavaConstant.InterfaceMethodRef(rdr));

            case JavaConstant.NameAndType.tag:
                return(new JavaConstant.NameAndType(rdr));

            case JavaConstant.MethodHandle.tag:
                return(new JavaConstant.MethodHandle(rdr));

            case JavaConstant.MethodType.tag:
                return(new JavaConstant.MethodType(rdr));

            case JavaConstant.InvokeDynamic.tag:
                return(new JavaConstant.InvokeDynamic(rdr));

            default:
                throw rdr.Where.Exception($"invalid tag {tag} in constant pool");
            }
        }
示例#11
0
 public LocalVariableTable(JavaReader rdr)
 {
     vars = new Item[rdr.Read16()];
     for (int i = 0; i < vars.Length; i++)
     {
         vars[i].offset      = rdr.Read16();
         vars[i].length      = rdr.Read16();
         vars[i].nameAndType = new JavaFieldRef(
             rdr.ConstUtf8(rdr.Read16()),
             rdr.ConstUtf8(rdr.Read16()),
             rdr.Where);
         vars[i].index = rdr.Read16();
     }
 }
示例#12
0
        public JavaConstantPool(JavaReader rdr)
        {
            var count = rdr.Read16();

            pool = new List <JavaConstant>(count + 1);
            pool.Add(null);
            for (int i = 1; i < count; i++)
            {
                var c = ReadConstant(rdr);
                pool.Add(c);
                if (c is JavaConstant.Long || c is JavaConstant.Double)
                {
                    i++;    // section 4.4.5
                    pool.Add(null);
                }
            }
        }
示例#13
0
        public JavaMethodHandle(JavaReader rdr, byte referenceKind, ushort referenceIndex)
        {
            Kind = (HandleKind)referenceKind;

            var  referenceType = rdr.ConstType(referenceIndex);
            bool ok            = false;

            if (Kind <= HandleKind.PutStatic)
            {
                if (referenceType == typeof(JavaConstant.FieldRef))
                {
                    (Class, Field) = rdr.ConstField(referenceIndex);
                    ok             = true;
                }
            }
            else if (Kind <= HandleKind.NewInvokeSpecial)
            {
                if (referenceType == typeof(JavaConstant.MethodRef))
                {
                    (Class, Method) = rdr.ConstMethod(referenceIndex);
                    ok = true;
                }
                else if (referenceType == typeof(JavaConstant.InterfaceMethodRef))
                {
                    (Class, Method)   = rdr.ConstInterfaceMethod(referenceIndex);
                    IsInterfaceMethod = true;
                    ok = true;
                }
            }
            else if (Kind == HandleKind.InvokeInterface)
            {
                if (referenceType == typeof(JavaConstant.InterfaceMethodRef))
                {
                    (Class, Method)   = rdr.ConstInterfaceMethod(referenceIndex);
                    IsInterfaceMethod = true;
                    ok = true;
                }
            }

            if (!ok)
            {
                throw rdr.Where.Exception("invalid method handle");
            }
        }
示例#14
0
        public static JavaClassEx ReadClassEx(System.IO.Compression.ZipArchiveEntry entry,
                                              bool withCode = true)
        {
            if (entry.Length > 4 &&
                (!string.IsNullOrEmpty(Path.GetFileName(entry.FullName))))
            {
                using (var stream = entry.Open())
                {
                    var(b0, b1, b2, b3) = (stream.ReadByte(), stream.ReadByte(),
                                           stream.ReadByte(), stream.ReadByte());
                    if (b0 == 0xCA && b1 == 0xFE && b2 == 0xBA && b3 == 0xBE)
                    {
                        using (var stream2 = new MemoryStream())
                        {
                            stream2.WriteByte((byte)b0);
                            stream2.WriteByte((byte)b1);
                            stream2.WriteByte((byte)b2);
                            stream2.WriteByte((byte)b3);
                            stream.CopyTo(stream2);
                            stream2.Position = 0;

                            var whereText = $"entry '{entry.FullName}' in archive";
                            var rdr       = new JavaReader(stream2, whereText, withCode);

                            if (rdr.Class != null)
                            {
                                rdr.Class.PackageNameLength =
                                    (short)Path.GetDirectoryName(entry.FullName).Length;

                                return(new JavaClassEx
                                {
                                    JavaClass = rdr.Class,
                                    Constants = rdr.constants,
                                    RawBytes = stream2.ToArray()
                                });
                            }
                        }
                    }
                }
            }
            return(null);
        }
示例#15
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();
     }
 }
示例#16
0
        public JavaMethod(JavaReader rdr, bool withCode = true)
        {
            Class = rdr.Class;

            Flags = (JavaAccessFlags)rdr.Read16();

            Name = rdr.ConstUtf8(rdr.Read16());

            rdr.Where.Push($"method '{Name}'");

            var tmpMethod = new JavaMethodRef(rdr.ConstUtf8(rdr.Read16()), rdr.Where);

            ReturnType = tmpMethod.ReturnType;
            Parameters = tmpMethod.Parameters;

            var attributes = new JavaAttributeSet(rdr, withCode);

            Exceptions = attributes.GetAttr <JavaAttribute.Exceptions>()?.classes;

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

            if (withCode && codeAttr != null)
            {
                #if !DEBUG
                try
                {
                #endif
                Code = new JavaCode(rdr, this, codeAttr);
                #if !DEBUG
            }
            catch (IndexOutOfRangeException)
            {
                throw rdr.Where.Exception("unexpected end of code");
            }
                #endif
            }

            InitParameterNames(attributes, codeAttr);

            rdr.Where.Pop();
        }
示例#17
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();
            }
示例#18
0
        void ReadCallSites(JavaReader rdr, JavaAttributeSet attributes)
        {
            if (rdr.callSites != null)
            {
                var attr = attributes.GetAttr <JavaAttribute.BootstrapMethods>();
                if (attr == null)
                {
                    throw rdr.Where.Exception($"missing bootstrap methods attribute");
                }

                var methods = attr.methods;
                foreach (var callSite in rdr.callSites)
                {
                    int i = callSite.BootstrapMethodIndex;
                    if (i >= methods.Length)
                    {
                        throw rdr.Where.Exception($"invalid bootstrap method index");
                    }

                    callSite.BootstrapMethod = methods[i].mh;
                    callSite.BootstrapArgs   = methods[i].args;
                }
            }
        }
示例#19
0
 public FieldRef(JavaReader rdr)
     : base(rdr)
 {
 }
示例#20
0
 public Integer(JavaReader rdr)
 {
     value = (int)rdr.Read32();
 }
示例#21
0
 public InvokeDynamic(JavaReader rdr)
 {
     bootstrapMethodIndex = rdr.Read16();
     nameAndTypeIndex     = rdr.Read16();
 }
示例#22
0
 public MethodType(JavaReader rdr)
 {
     descriptorIndex = rdr.Read16();
 }
示例#23
0
 public MethodHandle(JavaReader rdr)
 {
     referenceKind  = rdr.Read8();
     referenceIndex = rdr.Read16();
 }
示例#24
0
 public NameAndType(JavaReader rdr)
 {
     (nameIndex, descriptorIndex) = (rdr.Read16(), rdr.Read16());
 }
示例#25
0
 public InterfaceMethodRef(JavaReader rdr)
     : base(rdr)
 {
 }
示例#26
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();
        }
示例#27
0
 public MemberRef(JavaReader rdr)
 {
     (classIndex, nameAndTypeIndex) = (rdr.Read16(), rdr.Read16());
 }
示例#28
0
 public String(JavaReader rdr)
     : base(rdr)
 {
 }
示例#29
0
        public JavaAttributeSet(JavaReader rdr, bool withCode = true)
        {
            var count = rdr.Read16();

            set = new List <JavaAttribute>(count);

            for (int i = 0; i < count; i++)
            {
                var name = rdr.ConstUtf8(rdr.Read16());
                rdr.Where.Push($"attribute '{name}'");
                bool popped = false;

                var length   = JavaAttribute.ReadLength(rdr, name);
                var position = rdr.StreamPosition;

                JavaAttribute attr;
                switch (name)
                {
                case JavaAttribute.SourceFile.tag:
                    attr = new JavaAttribute.SourceFile(rdr);
                    break;

                case JavaAttribute.Signature.tag:
                    attr = new JavaAttribute.Signature(rdr);
                    break;

                case JavaAttribute.Exceptions.tag:
                    attr = new JavaAttribute.Exceptions(rdr);
                    break;

                case JavaAttribute.InnerClasses.tag:
                    attr = new JavaAttribute.InnerClasses(rdr);
                    break;

                case JavaAttribute.EnclosingMethod.tag:
                    attr = new JavaAttribute.EnclosingMethod(rdr);
                    break;

                case JavaAttribute.ConstantValue.tag:
                    attr = new JavaAttribute.ConstantValue(rdr);
                    break;

                case JavaAttribute.MethodParameters.tag:
                    attr = new JavaAttribute.MethodParameters(rdr);
                    break;

                //
                // Code attributes
                //

                case JavaAttribute.Code.tag:
                    attr = withCode ? (JavaAttribute) new JavaAttribute.Code(rdr)
                             : (JavaAttribute) new JavaAttribute.Generic(rdr, name, length);
                    break;

                case JavaAttribute.BootstrapMethods.tag:
                    attr = withCode ? (JavaAttribute) new JavaAttribute.BootstrapMethods(rdr)
                             : (JavaAttribute) new JavaAttribute.Generic(rdr, name, length);
                    break;

                case JavaAttribute.StackMapTable.tag:
                    attr = new JavaAttribute.StackMapTable(rdr);
                    break;

                case JavaAttribute.LineNumberTable.tag:
                    attr = new JavaAttribute.LineNumberTable(rdr);
                    break;

                case JavaAttribute.LocalVariableTable.tag:
                    attr = new JavaAttribute.LocalVariableTable(rdr);
                    break;

                //
                // Unhandled attributes
                //

                case "Synthetic":
                case "AnnotationDefault":
                case "LocalVariableTypeTable":
                case "RuntimeVisibleAnnotations":
                case "RuntimeInvisibleAnnotations":
                case "RuntimeInvisibleParameterAnnotations":
                case "Deprecated":
                    attr = new JavaAttribute.Generic(rdr, name, length);
                    break;

                default:
                    rdr.Where.Pop();
                    popped = true;
                    Console.WriteLine($"skipping unknown attribute '{name}'{rdr.Where}");
                    attr = new JavaAttribute.Generic(rdr, name, length);
                    break;
                }

                set.Add(attr);

                if (rdr.StreamPosition != position + length)
                {
                    throw rdr.Where.Exception("attribute too short");
                }

                if (!popped)
                {
                    rdr.Where.Pop();
                }
            }
        }
示例#30
0
 public MethodRef(JavaReader rdr)
     : base(rdr)
 {
 }