static void PrintField(IndentedText txt, FieldDefinition field) { byte[] initialValue = field.InitialValue; txt.Write("/* {0} */ {1}{2}{3}{4}{5} {6}{7}{8};", /* 0 */ ((uint)field.Attributes).ToString("X4"), /* 1 */ (field.IsPublic ? "public " : (field.IsPrivate ? "private " : (field.IsFamily ? "protected " : string.Empty))), /* 2 */ (field.IsStatic ? "static " : string.Empty), /* 3 */ (field.IsInitOnly ? "readonly " : string.Empty), /* 4 */ (field.IsNotSerialized ? "/* transient */ " : string.Empty), /* 5 */ field.FieldType.FullName, /* 6 */ field.Name, /* 7 */ (initialValue.Length != 0 ? " = bytes { " : string.Empty), /* 8 */ (field.HasConstant ? $" = ({field.Constant?.GetType()}) {field.Constant ?? "null"}" : string.Empty)); if (initialValue.Length != 0) { for (int i = 0; i < initialValue.Length; i++) { txt.Write("{0:X2} ", initialValue[i]); } txt.Write("};"); } txt.NewLine(); }
void PrintInstructionMisc1(IndentedText txt, Instruction inst, int offset) { if (inst.Data is int val) { txt.Write(instMnemonics[inst.Opcode] ?? "???"); txt.Write(" "); if (inst.Opcode == 0xBC) // newarray { txt.Write(val == 4 ? "boolean" : val == 5 ? "char" : val == 6 ? "float" : val == 7 ? "double" : val == 8 ? "byte" : val == 9 ? "short" : val == 10 ? "int" : val == 11 ? "long" : "unknown"); } else if (inst.Opcode == 0x11) // sipush { txt.Write("{0} (0x{0:X4})", (short)val); } else if (inst.Opcode == 0x10) // bipush { txt.Write("{0} (0x{0:X2})", (sbyte)val); } else { txt.Write("unknown misc opcode"); } } else { txt.Write("unknown misc opcode"); } }
void PrintInstructionJump(IndentedText txt, Instruction inst, int offset) { byte op = inst.Opcode; txt.Write(instMnemonics[op] ?? "???"); switch (instOperandType[op]) { case 0x42 when inst.Data is ushort targetLabel: txt.Write(" L.{0:X4}", targetLabel); break; case 0x44 when inst.Data is ushort targetLabelWide: txt.Write(" L.{0:X4}", targetLabelWide); break; case 0x4F when inst.Data is int[] switchData: txt.NewLine(); txt.AdjustIndent(+23); txt.Write("{0} default @ L.{1:X4}", instMnemonics[op], switchData[0]); int i0 = switchData[1]; for (int i = 3; i < switchData.Length; i++) { txt.Write(", case {0} @ L.{1:X4}", i + i0 - 3, switchData[i]); } txt.AdjustIndent(-23); break; default: txt.Write(" unknown jump opcode kind"); break; } }
static void PrintMethodBody(IndentedText txt, MethodBody body) { var numVars = body.HasVariables ? body.Variables.Count : 0; var numArgs = body.Method.HasParameters ? body.Method.Parameters.Count : 0; txt.Write("// stack={0}, locals={1}, args_size={2}, code_size={3}", body.MaxStackSize, numVars, numArgs, body.CodeSize); txt.NewLine(); txt.NewLine(); var exceptions = new Dictionary <int, List <string> >(); if (body.HasExceptionHandlers) { PrepareExceptions(body.ExceptionHandlers, exceptions); PrepareExceptions(null, exceptions); } foreach (var inst in body.Instructions) { if (exceptions.TryGetValue(inst.Offset, out var strs)) { txt.AdjustIndent(3); foreach (var s in strs) { txt.Write(s); txt.NewLine(); } txt.AdjustIndent(-3); } txt.Write(inst.ToString()); txt.NewLine(); } }
/* * JavaFieldPrinter */ public void Print(IndentedText txt) { txt.Write("/* {0} */ {1}{2}{3}{4}{5}{6} {7}", /* 0 */ ((ushort)Flags).ToString("X4"), /* 1 */ ((Flags & JavaAccessFlags.ACC_PUBLIC) != 0 ? "public " : ((Flags & JavaAccessFlags.ACC_PRIVATE) != 0 ? "private " : ((Flags & JavaAccessFlags.ACC_PROTECTED) != 0 ? "protected " : string.Empty))), /* 2 */ ((Flags & JavaAccessFlags.ACC_STATIC) != 0 ? "static " : string.Empty), /* 3 */ ((Flags & JavaAccessFlags.ACC_FINAL) != 0 ? "final " : string.Empty), /* 4 */ ((Flags & JavaAccessFlags.ACC_TRANSIENT) != 0 ? "transient " : string.Empty), /* 5 */ ((Flags & JavaAccessFlags.ACC_VOLATILE) != 0 ? "volatile " : string.Empty), /* 6 */ Type, /* 7 */ Name); if (Constant != null) { txt.Write(" = "); if (Constant is string) { txt.Write("\"{0}\"", Constant); } else { txt.Write(Constant.ToString()); } } txt.Write(";"); txt.NewLine(); }
static void PrintClassPrefix(IndentedText txt, JavaAccessFlags Flags, string Name) { if (Name == "interface") { Name = '\"' + Name + '\"'; } txt.Write("/* {0:X} */ {1}{2}{3}{4}{5} {6}", /* 0 */ ((ushort)Flags).ToString("X4"), /* 1 */ ((Flags & JavaAccessFlags.ACC_PUBLIC) != 0 ? "public " : string.Empty), /* 2 */ ((Flags & JavaAccessFlags.ACC_ABSTRACT) != 0 ? "abstract " : string.Empty), /* 3 */ ((Flags & JavaAccessFlags.ACC_STATIC) != 0 ? "static " : string.Empty), /* 4 */ ((Flags & JavaAccessFlags.ACC_FINAL) != 0 ? "final " : string.Empty), /* 5 */ ((Flags & JavaAccessFlags.ACC_INTERFACE) != 0 ? "interface" : ((Flags & JavaAccessFlags.ACC_ENUM) != 0 ? "enum" : "class")), /* 6 */ Name); }
void PrintInstructionWide(IndentedText txt, Instruction inst, int offset) { byte op = inst.Opcode; if (op == 0x84) { txt.Write("wide iinc?"); } else if (inst.Data is short val) { txt.Write("{0} {1} (wide)", instMnemonics[op] ?? "???", val); } else { txt.Write("unknown wide opcode"); } }
void PrintInstructionNarrow(IndentedText txt, Instruction inst, int offset) { byte op = inst.Opcode; if (op == 0x84) { sbyte value = (sbyte)((int)inst.Data & 0xFF); byte index = (byte)((int)inst.Data >> 8); txt.Write("{0} {1} {2}{3}", instMnemonics[op], index, (value >= 0 ? "+" : string.Empty), value); } else if (inst.Data is int val) { txt.Write("{0} {1}", instMnemonics[op] ?? "???", (int)inst.Data); } else { txt.Write("unknown narrow opcode"); } }
void PrintInstructionMisc0(IndentedText txt, Instruction inst, int offset) { byte op = inst.Opcode; byte op0 = 0; if (op >= 0x1A && op <= 0x1D) { op -= 0x1A; op0 = 0x15; // iload } else if (op >= 0x1E && op <= 0x21) { op -= 0x1E; op0 = 0x16; // lload } else if (op >= 0x22 && op <= 0x25) { op -= 0x22; op0 = 0x17; // fload } else if (op >= 0x26 && op <= 0x29) { op -= 0x26; op0 = 0x18; // dload } else if (op >= 0x2A && op <= 0x2D) { op -= 0x2A; op0 = 0x19; // aload } else if (op >= 0x3B && op <= 0x3E) { op -= 0x3B; op0 = 0x36; // istore } else if (op >= 0x3F && op <= 0x42) { op -= 0x3F; op0 = 0x37; // lstore } else if (op >= 0x43 && op <= 0x46) { op -= 0x43; op0 = 0x38; // fstore } else if (op >= 0x47 && op <= 0x4A) { op -= 0x47; op0 = 0x39; // dstore } else if (op >= 0x4B && op <= 0x4E) { op -= 0x4B; op0 = 0x3A; // astore } if (op0 == 0) { txt.Write(instMnemonics[op] ?? "???"); } else { txt.Write("{0}_{1}", instMnemonics[op0], op); } }
void PrintInstructionConst(IndentedText txt, Instruction inst, int offset) { txt.Write(instMnemonics[inst.Opcode] ?? "???"); if (inst.Class != null) { if (inst.Data == null) { txt.Write(" {0}", inst.Class); } else if (inst.Data is JavaMethodRef mr) { txt.Write(" ({0}) {1}.{2}(", mr.ReturnType, inst.Class, mr.Name); int numArgs = mr.Parameters?.Count ?? 0; for (int i = 0; i < numArgs; i++) { txt.Write("{0}{1}", /* 0 */ (i > 0 ? ", " : string.Empty), /* 1 */ mr.Parameters[i].Type); } txt.Write(")"); } else if (inst.Data is JavaFieldRef fr) { txt.Write(" ({0}) {1}.{2}", fr.Type, inst.Class, fr.Name); } else { txt.Write("???" + inst.Data + "???"); } } else if (inst.Data is JavaCallSite callSite) { txt.Write(" {0}", callSite.BootstrapMethod); txt.NewLine(); txt.AdjustIndent(+23); txt.Write("dynamic invocation name = {0}", callSite.InvokedMethod); txt.NewLine(); if (callSite.BootstrapArgs != null) { int n = callSite.BootstrapArgs.Length; txt.Write("bootstrap method arguments = "); for (int i = 0; i < n; i++) { txt.Write("{0}{1}", (i > 0 ? " ; " : ""), callSite.BootstrapArgs[i].ToString()); } } txt.AdjustIndent(-23); } else if (inst.Data is string strValue) { txt.Write(" \"{0}\"", strValue); } else if (inst.Data is int intValue) { txt.Write(" int {0} ({0:X8})", intValue, intValue); } else if (inst.Data is long longValue) { txt.Write(" long {0} ({0:X8})", longValue, longValue); } else if (inst.Data is float floatValue) { txt.Write(" float {0:F1}", floatValue); } else if (inst.Data is double doubeValue) { txt.Write(" double {0:F1}", doubeValue); } else { txt.Write(" unknown constant of type " + inst.Data.GetType()); } }
public void Print(IndentedText txt) { if (Instructions.Count == 0) { return; } if (instMnemonics == null) { InitializeMnemonics(); } var excStrings = PrepareExceptions(); int line = 0; string lineText; if (Instructions.Count > 0 && Instructions[0]?.Line != 0) { line = Instructions[0].Line; lineText = "line " + line + ", "; } else { lineText = string.Empty; } txt.Write(" ---------- {0}stack={1}, locals={2}, args_size={3}", lineText, MaxStack, MaxLocals, (Method.Parameters?.Count ?? 0)); txt.NewLine(); int offset = 0; foreach (var inst in Instructions) { if (inst.Line != 0 && inst.Line != line) { line = inst.Line; txt.Write(" ---------- line {0}", line); txt.NewLine(); } if (excStrings.TryGetValue(offset, out var strs)) { txt.AdjustIndent(+4); foreach (var s in strs) { txt.Write(s); txt.NewLine(); } txt.AdjustIndent(-4); } if (StackMap != null) { var(strLocals, strStack) = StackMap.FrameToString((ushort)offset); if (strLocals != null) { txt.Write($" locals = [ {strLocals} ]"); txt.NewLine(); } if (strStack != null) { txt.Write($" stack = [ {strStack} ]"); txt.NewLine(); } } byte op; if (inst.Bytes != null) { op = inst.Bytes[0]; txt.Write("{0:X4} {1:X2}", offset, op); for (int i = 1; i < inst.Bytes.Length; i++) { txt.Write(" {0:X2}", inst.Bytes[i]); } for (int i = inst.Bytes.Length; i < 5; i++) { txt.Write(" "); } txt.Write(" "); } else { op = inst.Opcode; txt.Write("L.{0:X4} {1:X2}", inst.Label, op); for (int i = 1; i < 5; i++) { txt.Write(" "); } txt.Write(" "); } if (op == 0xC4) { PrintInstructionWide(txt, inst, offset); } else { switch (instOperandType[op] & 0xF0) { case 0x80: PrintInstructionConst(txt, inst, offset); break; case 0x40: PrintInstructionJump(txt, inst, offset); break; case 0x20: PrintInstructionMisc1(txt, inst, offset); break; case 0x10: PrintInstructionNarrow(txt, inst, offset); break; case 0x00: PrintInstructionMisc0(txt, inst, offset); break; default: txt.Write("unknown opcode kind"); break; } } txt.NewLine(); if (inst.Bytes != null) { offset += inst.Bytes.Length; } } }
public void PrintJava(IndentedText txt) { if (SourceFile != null) { txt.Write("//"); txt.NewLine(); txt.Write("// {0}", SourceFile); txt.NewLine(); txt.Write("//"); txt.NewLine(); txt.NewLine(); } PrintClassPrefix(txt, Flags, Name); if (Super != null) { txt.Write(" extends {0}", Super); } if (Interfaces != null) { txt.Write(" implements "); for (int i = 0; i < Interfaces.Count; i++) { txt.Write("{0}{1}", (i > 0 ? ", " : string.Empty), Interfaces[i]); } } txt.Write(" {"); txt.NewLine(); txt.NewLine(); txt.AdjustIndent(true); if (Signature != null) { txt.Write("// signature "); txt.Write(Signature); txt.NewLine(); txt.NewLine(); } if (OuterAndInnerClasses != null) { if (OuterAndInnerClasses[0] != null) { if (OuterAndInnerClasses[0].InnerShortName != null) { txt.Write("// declared as {0} {{...}} in {1}", OuterAndInnerClasses[0].InnerShortName, OuterAndInnerClasses[0].OuterLongName); } else { txt.Write("// anonymous class {{...}} in {0}", OuterAndInnerClasses[0].OuterLongName); } txt.NewLine(); txt.NewLine(); } for (int i = 1; i < OuterAndInnerClasses.Length; i++) { PrintClassPrefix(txt, OuterAndInnerClasses[i].Flags, OuterAndInnerClasses[i].InnerShortName); txt.Write("{0} {{...}} is {1};", (OuterAndInnerClasses[i].InnerShortName == null ? "(anonymous)" : string.Empty), OuterAndInnerClasses[i].InnerLongName); txt.NewLine(); txt.NewLine(); } } if (Fields != null) { for (int i = 0; i < Fields.Count; i++) { Fields[i].Print(txt); txt.NewLine(); } } if (Methods != null) { for (int i = 0; i < Methods.Count; i++) { Methods[i].Print(txt); } } txt.AdjustIndent(false); txt.Write("}"); txt.NewLine(); txt.NewLine(); }
public static void PrintType(IndentedText txt, TypeDefinition type) { /*if (type.HasCustomAttributes) * PrintCustomAttributes(txt, type.CustomAttributes);*/ txt.Write("/* {0:X} */ {1}{2}{3}{4}{5}{6} {7}", /* 0 */ type.Attributes, /* 1 */ (type.IsPublic ? "public " : string.Empty), /* 2 */ (type.IsAbstract ? "abstract " : string.Empty), /* 3 */ (type.IsSealed ? "sealed " : string.Empty), /* 4 */ ((type.IsAbstract && type.IsSealed) ? "/* static */ " : string.Empty), /* 5 */ (type.IsSerializable ? "/* serializable */ " : string.Empty), /* 6 */ (type.IsInterface ? "interface" : "class"), /* 7 */ type.FullName); var baseType = type.BaseType; /*if (baseType != null && baseType.FullName == "System.Object") * baseType = null;*/ if (baseType != null || type.HasInterfaces) { txt.Write(" : "); bool comma = false; if (baseType != null) { txt.Write(baseType.FullName); comma = type.HasInterfaces; } if (type.HasInterfaces) { foreach (var intrface in type.Interfaces) { txt.Write("{0}{1}", (comma ? ", " : string.Empty), intrface.InterfaceType?.FullName ?? "(null)"); comma = true; } } } txt.Write(" {"); txt.NewLine(); txt.NewLine(); txt.AdjustIndent(true); foreach (var nested in type.NestedTypes) { PrintType(txt, nested); } if (type.HasNestedTypes) { txt.NewLine(); } foreach (var field in type.Fields) { PrintField(txt, field); } if (type.HasFields) { txt.NewLine(); } foreach (var method in type.Methods) { PrintMethod(txt, method); } txt.AdjustIndent(false); txt.Write("}"); txt.NewLine(); txt.NewLine(); }
static void PrintMethod(IndentedText txt, MethodDefinition method) { txt.Write("/* {0} */ {1}{2}{3}", /* 0 */ ((uint)method.Attributes).ToString("X4"), /* 1 */ (method.IsPublic ? "public " : (method.IsPrivate ? "private " : (method.IsFamily ? "protected " : (method.IsAssembly ? "internal " : string.Empty)))), /* 2 */ (method.IsStatic ? "static " : string.Empty), /* 3 */ (method.IsVirtual ? (method.IsNewSlot ? "virtual " : "override ") : string.Empty)); if (method.IsConstructor) { txt.Write(method.DeclaringType.FullName); } else { txt.Write("{0} {1}", method.ReturnType.FullName, method.Name); } txt.Write("("); int numArgs = 0; if (method.HasParameters) { bool comma = false; foreach (var arg in method.Parameters) { txt.Write("{0}{1} {2}", /* 0 */ (comma ? ", " : string.Empty), /* 1 */ arg.ParameterType.FullName, /* 2 */ arg.Name); comma = true; numArgs++; } } txt.Write(")"); txt.NewLine(); if (method.HasOverrides) { txt.AdjustIndent(true); foreach (var m in method.Overrides) { txt.Write("overrides " + m); txt.NewLine(); } txt.AdjustIndent(false); } if (method.HasBody) { txt.Write("{"); txt.NewLine(); txt.AdjustIndent(true); try { PrintMethodBody(txt, method.Body); } catch (Exception e) { foreach (var s in e.ToString().Split('\r', '\n')) { if (!string.IsNullOrEmpty(s)) { txt.Write(s); txt.NewLine(); } } } txt.AdjustIndent(false); txt.Write("}"); } txt.NewLine(); txt.NewLine(); }
public void Print(IndentedText txt) { txt.Write("/* {0} */ {1}{2}{3}", /* 0 */ ((ushort)Flags).ToString("X4"), /* 1 */ ((Flags & JavaAccessFlags.ACC_PUBLIC) != 0 ? "public " : ((Flags & JavaAccessFlags.ACC_PRIVATE) != 0 ? "private " : ((Flags & JavaAccessFlags.ACC_PROTECTED) != 0 ? "protected " : string.Empty))), /* 2 */ ((Flags & JavaAccessFlags.ACC_STATIC) != 0 ? "static " : ((Flags & JavaAccessFlags.ACC_ABSTRACT) != 0 ? "abstract " : string.Empty)), /* 3 */ ((Flags & JavaAccessFlags.ACC_FINAL) != 0 ? "final " : string.Empty)); if (Name == "<init>" || Name == "<clinit>") { txt.Write("{0}", Class.Name); } else { txt.Write("{0} {1}", ReturnType, Name); } txt.Write("("); for (int i = 0; i < Parameters.Count; i++) { txt.Write("{0}{1} {2}", /* 0 */ (i > 0 ? ", " : string.Empty), /* 1 */ Parameters[i].Type, /* 2 */ Parameters[i].Name); } txt.Write(")"); if (Exceptions != null) { for (int i = 0; i < Exceptions.Length; i++) { txt.Write("{0}{1}", /* 0 */ (i > 0 ? ", " : " throws "), /* 1 */ Exceptions[i].ClassName); } } if (Code != null) { txt.Write(" {"); txt.NewLine(); txt.AdjustIndent(true); Code.Print(txt); txt.AdjustIndent(false); txt.Write("}"); } else { txt.Write(";"); } txt.NewLine(); txt.NewLine(); }