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"); } }
/* * 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(); }
public Exceptions(JavaReader rdr) { classes = new JavaType[rdr.Read16()]; for (int i = 0; i < classes.Length; i++) { classes[i] = rdr.ConstClass(rdr.Read16()); } }
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(); } }
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(); } }
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; } } }
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); }
public Double(JavaReader rdr) { var blk = rdr.ReadBlock(8); if (BitConverter.IsLittleEndian) { Array.Reverse(blk); } value = BitConverter.ToDouble(blk, 0); }
public Float(JavaReader rdr) { var blk = rdr.ReadBlock(4); if (BitConverter.IsLittleEndian) { Array.Reverse(blk); } value = BitConverter.ToSingle(blk, 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"); } }
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(); } }
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); } } }
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"); } }
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); }
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 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(); }
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(); }
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; } } }
public FieldRef(JavaReader rdr) : base(rdr) { }
public Integer(JavaReader rdr) { value = (int)rdr.Read32(); }
public InvokeDynamic(JavaReader rdr) { bootstrapMethodIndex = rdr.Read16(); nameAndTypeIndex = rdr.Read16(); }
public MethodType(JavaReader rdr) { descriptorIndex = rdr.Read16(); }
public MethodHandle(JavaReader rdr) { referenceKind = rdr.Read8(); referenceIndex = rdr.Read16(); }
public NameAndType(JavaReader rdr) { (nameIndex, descriptorIndex) = (rdr.Read16(), rdr.Read16()); }
public InterfaceMethodRef(JavaReader rdr) : base(rdr) { }
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 MemberRef(JavaReader rdr) { (classIndex, nameAndTypeIndex) = (rdr.Read16(), rdr.Read16()); }
public String(JavaReader rdr) : base(rdr) { }
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(); } } }
public MethodRef(JavaReader rdr) : base(rdr) { }