public Exceptions(JavaReader rdr) { classes = new JavaType[rdr.Read16()]; for (int i = 0; i < classes.Length; i++) { classes[i] = rdr.ConstClass(rdr.Read16()); } }
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(); } }
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(); }
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(); }
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; } }
public ushort methodConst; // partial implementation public EnclosingMethod(JavaReader rdr) { className = rdr.ConstClass(rdr.Read16()).ClassName; methodConst = rdr.Read16(); }
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(); }