aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/ftbsc/lll/tools/debug/BytecodePrinter.java
blob: c08d85cecf4f1367c8523cea0dbb0ce467bc2a93 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package ftbsc.lll.tools.debug;

import org.apache.logging.log4j.Logger;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.util.Printer;
import org.objectweb.asm.util.Textifier;
import org.objectweb.asm.util.TraceMethodVisitor;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Paths;

/**
 * A collection of static methods for debugging by printing the ASM bytecode.
 * These methods are only for debug, so most of the time they should stay unused.
 */
public class BytecodePrinter {

   /**
    * Used for converting visit events to text, acts pretty much like a buffer in our case.
    */
   private static final Printer PRINTER = new Textifier();

   /**
    * MethodVisitor that visits the method and prints it to a given printer.
    */
   private static final TraceMethodVisitor MP = new TraceMethodVisitor(PRINTER);

   /**
    * Prints the bytecode of a method using System.out.print().
    * @param main the method to print
    */
   public static void printAsmMethod(final MethodNode main) {
      for (AbstractInsnNode i : main.instructions.toArray())
         System.out.print(insnToString(i));
   }

   /**
    * Logs the bytecode of a method using the ASM logger.
    * @param main the method to print
    * @param logger the Log4j {@link Logger} to print it with
    */
   public static void logAsmMethod(final MethodNode main, final Logger logger) {
      for (AbstractInsnNode i : main.instructions.toArray())
         logger.debug(insnToString(i));
   }

   /**
    * Logs the bytecode of a method to a file.
    * @param main the method to print
    * @param path the file to log it to
    */
   public static void logAsmMethod(final MethodNode main, String path) {
      StringBuilder out = new StringBuilder();
      for (AbstractInsnNode i : main.instructions.toArray())
         out.append(insnToString(i));
      try {
         Files.write(Paths.get(path), out.toString().getBytes());
      } catch (IOException e) {
         e.printStackTrace();
      }
   }

   /**
    * Converts an instruction node to a String.
    * @param insn the node to convert
    * @return the converted string
    */
   public static String insnToString(AbstractInsnNode insn) {
      insn.accept(MP);
      StringWriter sw = new StringWriter();
      PRINTER.print(new PrintWriter(sw));
      PRINTER.getText().clear();
      return sw.toString();
   }
}