package eu.bibl.cfide.engine.decompiler; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.FieldInsnNode; import org.objectweb.asm.tree.FrameNode; import org.objectweb.asm.tree.IincInsnNode; import org.objectweb.asm.tree.InsnNode; import org.objectweb.asm.tree.IntInsnNode; import org.objectweb.asm.tree.JumpInsnNode; import org.objectweb.asm.tree.LabelNode; import org.objectweb.asm.tree.LdcInsnNode; import org.objectweb.asm.tree.LineNumberNode; import org.objectweb.asm.tree.LookupSwitchInsnNode; import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.MultiANewArrayInsnNode; import org.objectweb.asm.tree.TableSwitchInsnNode; import org.objectweb.asm.tree.TypeInsnNode; import org.objectweb.asm.tree.VarInsnNode; import eu.bibl.banalysis.asm.insn.InstructionPrinter; import eu.bibl.cfide.context.CFIDEContext; import eu.bibl.cfide.io.config.CFIDEConfig; public class AdvancedInstructionPrinter extends InstructionPrinter { protected CFIDEContext context; public AdvancedInstructionPrinter(CFIDEContext context, MethodNode m) { super(m); this.context = context; } @Override public ArrayList<String> createPrint() { ArrayList<String> info = new ArrayList<String>(); ListIterator<?> it = mNode.instructions.iterator(); while (it.hasNext()) { AbstractInsnNode ain = (AbstractInsnNode) it.next(); String line = ""; if (ain instanceof VarInsnNode) { line = printVarInsnNode((VarInsnNode) ain, it); } else if (ain instanceof IntInsnNode) { line = printIntInsnNode((IntInsnNode) ain, it); } else if (ain instanceof FieldInsnNode) { line = printFieldInsnNode((FieldInsnNode) ain, it); } else if (ain instanceof MethodInsnNode) { line = printMethodInsnNode((MethodInsnNode) ain, it); } else if (ain instanceof LdcInsnNode) { line = printLdcInsnNode((LdcInsnNode) ain, it); } else if (ain instanceof InsnNode) { line = printInsnNode((InsnNode) ain, it); } else if (ain instanceof JumpInsnNode) { line = printJumpInsnNode((JumpInsnNode) ain, it); } else if (ain instanceof LineNumberNode) { line = printLineNumberNode((LineNumberNode) ain, it); } else if (ain instanceof LabelNode) { line = printLabelnode((LabelNode) ain); } else if (ain instanceof TypeInsnNode) { line = printTypeInsnNode((TypeInsnNode) ain); } else if (ain instanceof FrameNode) { line = ""; } else if (ain instanceof IincInsnNode) { line = printIincInsnNode((IincInsnNode) ain); } else if (ain instanceof TableSwitchInsnNode) { line = printTableSwitchInsnNode((TableSwitchInsnNode) ain); } else if (ain instanceof LookupSwitchInsnNode) { line = printLookupSwitchInsnNode((LookupSwitchInsnNode) ain); } else if (ain instanceof MultiANewArrayInsnNode) {// HOLY FUCKING SHIT THIS WASNT IMPLEMENTED line = printMultiANewArrayInsnNode((MultiANewArrayInsnNode) ain, it); } else { line += "UNKNOWN-NODE: " + nameOpcode(ain.getOpcode()) + " " + ain.toString(); } if (!line.equals("")) { // if (match) dont use match because -> is used otherwhere // if (matchedInsns.contains(ain)) // line = " -> " + line; info.add(line); } } return info; } protected String printMultiANewArrayInsnNode(MultiANewArrayInsnNode ain, ListIterator<?> it) { return nameOpcode(ain.getOpcode()) + " " + ain.desc + " " + ain.dims; } @Override protected String printLineNumberNode(LineNumberNode lin, ListIterator<?> it) { if (context.config.getProperty(CFIDEConfig.DECOMPILER_METHOD_PRINT_LINE_NUMBERS, true)) { return " <line:" + lin.line + ">"; } return ""; } @Override protected String printLdcInsnNode(LdcInsnNode ldc, ListIterator<?> it) { if (ldc.cst instanceof String) return nameOpcode(ldc.getOpcode()) + " \"" + escapeJavaStyleString(ldc.cst.toString(), true) + "\" (" + ldc.cst.getClass().getCanonicalName() + ")"; return nameOpcode(ldc.getOpcode()) + " " + escapeJavaStyleString(ldc.cst.toString(), true) + " (" + ldc.cst.getClass().getCanonicalName() + ")"; } @Override protected String printTableSwitchInsnNode(TableSwitchInsnNode tin) { String line = nameOpcode(tin.getOpcode()) + " \n"; List<?> labels = tin.labels; int count = 0; for (int i = tin.min; i < tin.max; i++) { line += " val: " + i + " -> " + "L" + resolveLabel((LabelNode) labels.get(count++)) + "\n"; } line += " default" + " -> L" + resolveLabel(tin.dflt) + ""; return line; } @Override protected String printLookupSwitchInsnNode(LookupSwitchInsnNode lin) { String line = nameOpcode(lin.getOpcode()) + ": \n"; List<?> keys = lin.keys; List<?> labels = lin.labels; for (int i = 0; i < keys.size(); i++) { int key = (Integer) keys.get(i); LabelNode label = (LabelNode) labels.get(i); line += " val: " + key + " -> " + "L" + resolveLabel(label) + "\n"; } line += " default" + " -> L" + resolveLabel(lin.dflt) + ""; return line; } @Override protected String printJumpInsnNode(JumpInsnNode jin, ListIterator<?> it) { String line = nameOpcode(jin.getOpcode()) + " L" + resolveLabel(jin.label); return line; } @Override protected String printLabelnode(LabelNode label) { return "L" + resolveLabel(label) + ":"; } @Override protected int resolveLabel(LabelNode ln) { return super.resolveLabel(ln); } @Override protected String printFieldInsnNode(FieldInsnNode fin, ListIterator<?> it) { return nameOpcode(fin.getOpcode()) + " " + fin.owner + "." + fin.name + ":" + fin.desc; } @Override protected String printMethodInsnNode(MethodInsnNode min, ListIterator<?> it) { return nameOpcode(min.getOpcode()) + " " + min.owner + "." + min.name + ":" + min.desc; } public static String escapeJavaStyleString(String str, boolean escapeSingleQuote) { if (str == null) { return ""; } int sz = str.length(); StringBuilder sb = new StringBuilder(sz); for (int i = 0; i < sz; i++) { char ch = str.charAt(i); // handle unicode if (ch > 0xfff) { sb.append("\\u" + hex(ch)); } else if (ch > 0xff) { sb.append("\\u0" + hex(ch)); } else if (ch > 0x7f) { sb.append("\\u00" + hex(ch)); } else if (ch < 32) { switch (ch) { case '\b': sb.append('\\'); sb.append('b'); break; case '\n': sb.append('\\'); sb.append('n'); break; case '\t': sb.append('\\'); sb.append('t'); break; case '\f': sb.append('\\'); sb.append('f'); break; case '\r': sb.append('\\'); sb.append('r'); break; default: if (ch > 0xf) { sb.append("\\u00" + hex(ch)); } else { sb.append("\\u000" + hex(ch)); } break; } } else { switch (ch) { case '\'': if (escapeSingleQuote) { sb.append('\\'); } sb.append('\''); break; case '"': sb.append('\\'); sb.append('"'); break; case '\\': sb.append('\\'); sb.append('\\'); break; default: sb.append(ch); break; } } } return sb.toString(); } public static String hex(char ch) { return Integer.toHexString(ch).toUpperCase(); } }