Package nf.co.haxter.util

Source Code of nf.co.haxter.util.BytecodeUtils

package nf.co.haxter.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;

import nf.co.haxter.customized.CustomLabel;
import nf.co.haxter.exception.InvalidBytecodeException;

import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
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.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.IntInsnNode;
import org.objectweb.asm.tree.InvokeDynamicInsnNode;
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.MethodInsnNode;
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 org.objectweb.asm.util.Printer;
import org.objectweb.asm.util.Textifier;

/**
* A utility class for bytecode-related tasks.
*
* @author blootooby
*/
public final class BytecodeUtils implements Opcodes {
  /**
   * Turns a textual representation of bytecode into actual bytecode.
   *
   * @param scriptLines A script of bytecode instruction representations.
   * @return A list of instruction nodes created from the <code>scriptLines</code>.
   * @throws InvalidBytecodeException If the script was invalid.
   */
  public static InsnList generateInsnListFromScript(String[] scriptLines)
      throws InvalidBytecodeException {
    InsnList ret = new InsnList();
    for (String line : scriptLines) {
      String[] args = MiscUtils.translateCommandline(line);

      /*
       * for (int i = 0; i < args.length; i++) { // FIXME if (args[i].contains(" ")) { args[i] = '"'
       * + args[i]; } }
       */

      ret.add(getNodeFromArgs(args));
    }

    // Generate actual labels.
    Map<Integer, LabelNode> labelz = new HashMap<Integer, LabelNode>();
    ListIterator<AbstractInsnNode> li = ret.iterator();
    AbstractInsnNode ain = li.hasNext() ? null : li.next();
    for (int i = 0; li.hasNext(); ain = li.next(), i++) {
      if (ain instanceof LineNumberNode) {
        LineNumberNode lnn = (LineNumberNode) ain;
        LabelNode cl = labelz.get(lnn.start.getLabel().getOffset());
        if (cl == null) {
          labelz.put(lnn.start.getLabel().getOffset(), lnn.start);
        } else {
          lnn.start = cl;
        }
      } else if (ain instanceof JumpInsnNode) {
        JumpInsnNode jin = (JumpInsnNode) ain;
        LabelNode cl = labelz.get(jin.label.getLabel().getOffset());
        if (cl == null) {
          labelz.put(jin.label.getLabel().getOffset(), jin.label);
        } else {
          jin.label = cl;
        }
      } else if (ain instanceof TableSwitchInsnNode) {
        TableSwitchInsnNode tsin = (TableSwitchInsnNode) ain;
        LabelNode cl = labelz.get(tsin.dflt.getLabel().getOffset());
        if (cl == null) {
          labelz.put(tsin.dflt.getLabel().getOffset(), tsin.dflt);
        } else {
          tsin.dflt = cl;
        }
      }
    }
    Map<AbstractInsnNode, LabelNode> nodeMap = new HashMap<AbstractInsnNode, LabelNode>();
    for (Entry<Integer, LabelNode> e : labelz.entrySet()) {
      nodeMap.put(ret.get(e.getKey()), e.getValue());
    }


    System.out.println("Adding labels!");
    for (Entry<AbstractInsnNode, LabelNode> e : nodeMap.entrySet()) {
      System.out.println(String.format("%s -> %s", e.getKey(), e.getValue()));
      ret.insertBefore(e.getKey(), e.getValue());
    }
    System.out.println("Added labels.");


    return ret;
  }

  /**
   * Translates the string representation of an opcode to the integer representation.
   *
   * @param opcode the string representation of the opcode.
   * @return the integer representation of the opcode, or -1 if the opcode was not found.
   */
  public static int getOpcodeFromString(String opcode) {
    if (opcode == null || opcode.length() == 0) {
      return -1;
    }
    for (int i = 0; i < Printer.OPCODES.length; i++) {
      String s = Printer.OPCODES[i];
      if (s != null && s.equals(opcode)) {
        return i;
      }
    }
    return -1;
  }

  /**
   * Translates the string representation of an operand type to the integer representation. Used
   * only for BIPUSH and SIPUSH.
   *
   * @param type the string representation of the operand type.
   * @return the integer representation of the operand type, or -1 if the operand type was not
   *         found.
   */
  public static int getOperandTypeFromString(String type) {
    if (type == null || type.length() == 0) {
      return -1;
    }
    for (int i = 0; i < Printer.TYPES.length; i++) {
      String s = Printer.TYPES[i];
      if (s != null && s.equals(type)) {
        return i;
      }
    }
    return -1;
  }

  /**
   * Turns a string representation of a bytecode instruction into an instruction node.
   *
   * @param args strings representing the instruction.
   * @return an instruction node made from the <code>args</code>.
   * @throws InvalidBytecodeException If the string representation was invalid.
   */
  public static AbstractInsnNode getNodeFromArgs(String[] args) throws InvalidBytecodeException {
    int opcode = getOpcodeFromString(args[0].toUpperCase());
    switch (opcode) {
      case NOP:
      case ACONST_NULL:
      case ICONST_M1:
      case ICONST_0:
      case ICONST_1:
      case ICONST_2:
      case ICONST_3:
      case ICONST_4:
      case ICONST_5:
      case LCONST_0:
      case LCONST_1:
      case FCONST_0:
      case FCONST_1:
      case FCONST_2:
      case DCONST_0:
      case DCONST_1:
      case IALOAD:
      case LALOAD:
      case FALOAD:
      case DALOAD:
      case AALOAD:
      case BALOAD:
      case CALOAD:
      case SALOAD:
      case IASTORE:
      case LASTORE:
      case FASTORE:
      case DASTORE:
      case AASTORE:
      case BASTORE:
      case CASTORE:
      case SASTORE:
      case POP:
      case POP2:
      case DUP:
      case DUP_X1:
      case DUP_X2:
      case DUP2:
      case DUP2_X1:
      case DUP2_X2:
      case SWAP:
      case IADD:
      case LADD:
      case DADD:
      case FADD:
      case ISUB:
      case LSUB:
      case DSUB:
      case FSUB:
      case IMUL:
      case LMUL:
      case DMUL:
      case FMUL:
      case IDIV:
      case LDIV:
      case DDIV:
      case FDIV:
      case IREM:
      case LREM:
      case DREM:
      case FREM:
      case INEG:
      case LNEG:
      case DNEG:
      case FNEG:
      case ISHL:
      case LSHL:
      case ISHR:
      case LSHR:
      case IUSHR:
      case LUSHR:
      case IAND:
      case LAND:
      case IXOR:
      case LXOR:
      case I2L:
      case I2F:
      case I2D:
      case L2I:
      case L2F:
      case L2D:
      case F2L:
      case F2D:
      case F2I:
      case D2I:
      case D2L:
      case D2F:
      case I2B:
      case I2C:
      case I2S:
      case LCMP:
      case FCMPL:
      case FCMPG:
      case DCMPL:
      case DCMPG:
      case IRETURN:
      case FRETURN:
      case DRETURN:
      case LRETURN:
      case ARETURN:
      case RETURN:
      case ARRAYLENGTH:
      case ATHROW:
      case MONITORENTER:
      case MONITOREXIT:
        return new InsnNode(opcode);

      case ILOAD:
      case FLOAD:
      case DLOAD:
      case LLOAD:
      case ALOAD:
      case ISTORE:
      case LSTORE:
      case FSTORE:
      case DSTORE:
      case ASTORE:
      case RET:
        return new VarInsnNode(opcode, toint(args[1]));

      case GETSTATIC:
      case PUTSTATIC:
      case GETFIELD:
      case PUTFIELD:
        return new FieldInsnNode(opcode, args[1], args[2], args[3]);

      case INVOKESTATIC:
      case INVOKEVIRTUAL:
      case INVOKESPECIAL:
      case INVOKEINTERFACE:
        return new MethodInsnNode(opcode, args[1], args[2], args[3], tobool(args[4]));
      case INVOKEDYNAMIC:
        if (args.length < 7) {
          return new InvokeDynamicInsnNode(args[1], args[2], new Handle(toint(args[3]), args[4],
              args[5], args[6]));
        }// else {
         //
         // for (int i = 7; i < args.length; i++) {
         //
         // }
         // }
         // TODO fuck it, I'll do the bsmArgs version another day. >:(

      case IFEQ:
      case IFNE:
      case IFLT:
      case IFGT:
      case IFLE:
      case IFGE:
      case IF_ICMPEQ:
      case IF_ICMPNE:
      case IF_ICMPLT:
      case IF_ICMPGE:
      case IF_ICMPGT:
      case IF_ICMPLE:
      case IF_ACMPEQ:
      case IF_ACMPNE:
      case GOTO:
      case JSR:
      case IFNULL:
      case IFNONNULL:
        return new JumpInsnNode(opcode, getLabelNode(toint(args[1]))); // this was annoying to do.

      case BIPUSH:
      case SIPUSH:
        return new IntInsnNode(opcode, toint(args[1]));
      case NEWARRAY:
        return new IntInsnNode(opcode, getOperandTypeFromString(args[1]));

      case LDC:
        if (args[1].charAt(0) == '"') {
          return new LdcInsnNode(args[1].replace("\\n", "\n").substring(1));
        } else if (args[1].charAt(0) == 'L' && args[1].charAt(args[1].length()) == ';') {
          return new LdcInsnNode(Type.getType(args[1]));
        } else {
          System.out.println(args[1]);
          char c = args[1].charAt(args[1].length());
          switch (c) {
            case 'D':
            case 'd':
              return new LdcInsnNode(todouble(args[1]));
            case 'F':
            case 'f':
              return new LdcInsnNode(tofloat(args[1]));
            case 'L':
            case 'l':
              return new LdcInsnNode(tolong(args[1]));
            default:
              return new LdcInsnNode(toint(args[1]));
          }
        }

      case NEW:
      case ANEWARRAY:
      case CHECKCAST:
      case INSTANCEOF:
        return new TypeInsnNode(opcode, args[1]);

      case -1:
        switch (args[0].toUpperCase()) {
          case "LINE":
          case "LINENUMBER":
            return new LineNumberNode(toint(args[1]), getLabelNode(toint(args[2])));// FIXME
          case "MULTIANEWARRAY":
            return new MultiANewArrayInsnNode(args[1], toint(args[2]));
          case "TABLESWITCH":
          case "SWITCH":
            return new TableSwitchInsnNode(toint(args[1]), toint(args[2]),
                getLabelNode(toint(args[3])), getLabelNode(toint(args[4]))); // FIXME arg4 is a
                                                                             // varargs
          case "IINC":
            return new IincInsnNode(toint(args[1]), toint(args[2]));
          case "FRAME":
            switch (args[1].toUpperCase()) {
              case "SAME":
                return new FrameNode(F_SAME, 0, null, 0, null);

              case "SAME1":
                switch (Character.toUpperCase(args[2].charAt(0))) {
                  case 'T':
                    return new FrameNode(F_SAME1, 0, null, 1, new Object[] {0});
                  case 'I':
                    return new FrameNode(F_SAME1, 0, null, 1, new Object[] {1});
                  case 'F':
                    return new FrameNode(F_SAME1, 0, null, 1, new Object[] {2});
                  case 'D':
                    return new FrameNode(F_SAME1, 0, null, 1, new Object[] {3});
                  case 'J':
                    return new FrameNode(F_SAME1, 0, null, 1, new Object[] {4});
                  case 'N':
                    return new FrameNode(F_SAME1, 0, null, 1, new Object[] {5});
                  case 'U':
                    return new FrameNode(F_SAME1, 0, null, 1, new Object[] {6});
                  case 'L':
                    return new FrameNode(F_SAME1, 0, null, 1, new Object[] {new Label()});// FIXME
                  case '[':
                  default:
                    return new FrameNode(F_SAME1, 0, null, 1, new Object[] {args[2]});
                }

              case "CHOP":
                return new FrameNode(F_CHOP, toint(args[2]), null, 0, null);

              case "FULL":
              case "NEW": {// DAMN THIS IS GONNA SUCK DDD:
                boolean doingLocals = true;
                boolean done = false;

                List<Object> locals = new ArrayList<Object>();
                List<Object> stack = new ArrayList<Object>();
                for (int i = 2; i < args.length; i++) {
                  if (args[i].length() > 0) {
                    String part = args[i];
                    if (part.charAt(0) == '[') {
                      part = part.substring(1);
                    } else if (part.endsWith("]")) {
                      if (!doingLocals) {
                        done = true;
                      } else {
                        locals.add(part.substring(0, part.length() - 1));

                        doingLocals = false;
                      }
                      part = part.substring(0, part.length() - 1);

                      switch (Character.toUpperCase(args[i].charAt(0))) {
                        case 'T':
                          (doingLocals ? locals : stack).add(0);
                        case 'I':
                          (doingLocals ? locals : stack).add(1);
                        case 'F':
                          (doingLocals ? locals : stack).add(2);
                        case 'D':
                          (doingLocals ? locals : stack).add(3);
                        case 'J':
                          (doingLocals ? locals : stack).add(4);
                        case 'N':
                          (doingLocals ? locals : stack).add(5);
                        case 'U':
                          (doingLocals ? locals : stack).add(6);
                        case 'L':
                          (doingLocals ? locals : stack).add(new CustomLabel(toint(part
                              .substring(1))));
                        case '[':
                        default:
                          (doingLocals ? locals : stack).add(args[i]);
                      }
                    }
                    if (done) {
                      break;
                    }
                  }
                }
                return new FrameNode(args[1].equalsIgnoreCase("new") ? F_NEW : F_FULL,
                    locals.size(), locals.toArray(), stack.size(), stack.toArray());
              }
              case "APPEND": {
                boolean done = false;
                List<Object> locals = new ArrayList<Object>();
                for (int i = 2; i < args.length; i++) {
                  String part = args[i];
                  if (part.length() > 0) {
                    if (part.charAt(0) == '[') {
                      part = part.substring(1);
                    } else if (part.endsWith("]")) {
                      done = true;
                      part = part.substring(0, part.length() - 1);
                    }
                    if (!part.contains("/")) {
                      switch (Character.toUpperCase(part.charAt(0))) {
                        case 'T':
                          locals.add(0);
                        case 'I':
                          locals.add(1);
                        case 'F':
                          locals.add(2);
                        case 'D':
                          locals.add(3);
                        case 'J':
                          locals.add(4);
                        case 'N':
                          locals.add(5);
                        case 'U':
                          locals.add(6);
                        case 'L':
                          locals.add(new CustomLabel(toint(part.substring(1))));
                        case '[':
                        default:
                          locals.add(part);
                      }
                    } else {
                      locals.add(part);
                    }



                  }

                  if (done) {
                    break;
                  }
                }
                return new FrameNode(F_APPEND, locals.size(), locals.toArray(), 0, null);
              }
            }
        }
        throw new InvalidBytecodeException(args);

      default:
        throw new InvalidBytecodeException(args);
    }
  }


  public static List<String> bytecodeToText(InsnList instructions) {
    List<String> ret = new ArrayList<String>();
    ListIterator<AbstractInsnNode> li = instructions.iterator();
    while (li.hasNext()) {
      AbstractInsnNode ain = li.next();

      String textOpcode = "";
      if (ain.getOpcode() != -1) {
        textOpcode = Printer.OPCODES[ain.getOpcode()];
      } else {
        // oh boy, special case. yaaay :(
      }
      String fullInsn = textOpcode;
      switch (ain.getType()) {
        case AbstractInsnNode.FIELD_INSN:
          FieldInsnNode fin = (FieldInsnNode) ain;
          fullInsn += ' ' + fin.owner;
          fullInsn += ' ' + fin.name;
          fullInsn += ' ' + fin.desc;
          break;
        case AbstractInsnNode.JUMP_INSN:
          JumpInsnNode jin = (JumpInsnNode) ain;
          try {
            int offset = getLabelOffset(jin.label.getLabel(), instructions); // YAY FIXED
            fullInsn += " " + offset;
          } catch (Exception e) {
            e.printStackTrace();
            fullInsn += " [offset not resolved! :(]";
          }
          break;
        case AbstractInsnNode.IINC_INSN:
          IincInsnNode iin = (IincInsnNode) ain;
          fullInsn += " " + iin.var;
          fullInsn += " " + iin.incr;
          break;
        case AbstractInsnNode.LOOKUPSWITCH_INSN:
        case AbstractInsnNode.INSN:
          break;
        case AbstractInsnNode.LDC_INSN:
          LdcInsnNode lin = (LdcInsnNode) ain;
          if (lin.cst instanceof String) {
            fullInsn += " \"" + ((String) lin.cst).replace("\n", "\\n") + "\"";
          } else if (lin.cst instanceof Type) {
            fullInsn += ' ' + ((Type) lin.cst).getDescriptor();
          } else {
            fullInsn += " " + lin.cst;
          }
          break;
        case AbstractInsnNode.INT_INSN:
          IntInsnNode iin1 = (IntInsnNode) ain;
          fullInsn += " " + iin1.operand;
          break;
        case AbstractInsnNode.LINE:
          fullInsn =
              "LINENUMBER " + ((LineNumberNode) ain).line + " "
                  + getLabelOffset(((LineNumberNode) ain).start.getLabel(), instructions);
          break;
        case AbstractInsnNode.METHOD_INSN:
          MethodInsnNode min = (MethodInsnNode) ain;
          fullInsn += ' ' + min.owner;
          fullInsn += ' ' + min.name;
          fullInsn += ' ' + min.desc;
          fullInsn += " " + min.itf;
          break;
        case AbstractInsnNode.MULTIANEWARRAY_INSN:
          MultiANewArrayInsnNode manin = (MultiANewArrayInsnNode) ain;
          fullInsn += ' ' + manin.desc;
          fullInsn += " " + manin.dims;
          break;
        case AbstractInsnNode.TABLESWITCH_INSN:
          TableSwitchInsnNode tsin = (TableSwitchInsnNode) ain;
          fullInsn += " " + tsin.min;
          fullInsn += " " + tsin.max;
          fullInsn += ' ' + tsin.dflt.getLabel().getOffset();
          for (LabelNode ln : (List<LabelNode>) tsin.labels) {
            fullInsn += ' ' + ln.getLabel().getOffset();
          }
          break;
        case AbstractInsnNode.TYPE_INSN:
          TypeInsnNode tin = (TypeInsnNode) ain;
          fullInsn += ' ' + tin.desc;
          break;
        case AbstractInsnNode.VAR_INSN:
          VarInsnNode vin = (VarInsnNode) ain;
          fullInsn += " " + vin.var;
          break;
        case AbstractInsnNode.LABEL:
          continue;
        case AbstractInsnNode.INVOKE_DYNAMIC_INSN:
          InvokeDynamicInsnNode idin = (InvokeDynamicInsnNode) ain;
          // idin.
          // TODO all of invokedynamic.
          break;
        case AbstractInsnNode.FRAME:
          FrameNode fn = (FrameNode) ain;
          fullInsn = translateFrameToText(fn, instructions);
          break;


      // TODO the rest.
      }
      ret.add(fullInsn);
    }

    return ret;
  }

  public static String translateFrameToText(FrameNode fn, InsnList instructions) {
    String ret = "FRAME ";
    switch (fn.type) {
      case F_NEW:
      case F_FULL:
        ret += fn.type == F_NEW ? "NEW [" : "FULL [";
        ret = appendFrameTypes(ret, instructions, fn.local.size(), fn.local.toArray());
        ret += "] [";
        ret = appendFrameTypes(ret, instructions, fn.stack.size(), fn.stack.toArray());
        return ret + ']';
      case F_APPEND:
        ret += "APPEND [";
        ret = appendFrameTypes(ret, instructions, fn.local.size(), fn.local.toArray());
        return ret + ']';
      case F_CHOP:
        return "FRAME CHOP " + fn.local.size();
      case F_SAME:
        return "FRAME SAME";
      case F_SAME1:
        ret += "SAME1 ";
        ret = appendFrameTypes(ret, instructions, 1, fn.stack.toArray());
        return ret;
      default:
        return "FRAME";
    }
  }

  public static String appendFrameTypes(String buf, InsnList instructions, final int n,
      final Object[] o) {
    for (int i = 0; i < n; ++i) {
      if (i > 0) {
        buf += ' ';
      }
      if (o[i] instanceof String) {
        String desc = (String) o[i];
        if (desc.startsWith("[")) {
          buf = appendDescriptor(buf, Textifier.FIELD_DESCRIPTOR, desc);
        } else {
          buf = appendDescriptor(buf, Textifier.INTERNAL_NAME, desc);
        }
      } else if (o[i] instanceof Integer) {
        switch (((Integer) o[i]).intValue()) {
          case 0:
            buf = appendDescriptor(buf, Textifier.FIELD_DESCRIPTOR, "T");
            break;
          case 1:
            buf = appendDescriptor(buf, Textifier.FIELD_DESCRIPTOR, "I");
            break;
          case 2:
            buf = appendDescriptor(buf, Textifier.FIELD_DESCRIPTOR, "F");
            break;
          case 3:
            buf = appendDescriptor(buf, Textifier.FIELD_DESCRIPTOR, "D");
            break;
          case 4:
            buf = appendDescriptor(buf, Textifier.FIELD_DESCRIPTOR, "J");
            break;
          case 5:
            buf = appendDescriptor(buf, Textifier.FIELD_DESCRIPTOR, "N");
            break;
          case 6:
            buf = appendDescriptor(buf, Textifier.FIELD_DESCRIPTOR, "U");
            break;
        }
      } else if (o[i] instanceof Label) {
        buf += "L" + getLabelOffset((Label) o[i], instructions);
      } else {
        throw new Error("Invalid frame parts!");
      }
    }
    return buf;
  }

  private static String appendDescriptor(String buf, final int type, final String desc) {
    if (type == Textifier.CLASS_SIGNATURE || type == Textifier.FIELD_SIGNATURE
        || type == Textifier.METHOD_SIGNATURE) {
      if (desc != null) {
        buf += desc + '\n'; // TODO look into this later. (signatures)
      }
    } else {
      buf += desc;
    }
    return buf;
  }



  /**
   * A convenience method for converting a {@link String} to an <code>int</code>.
   *
   * @param s {@link String} to parse.
   * @return the converted <code>int</code>.
   * @throws NumberFormatException If the {@link String} failed to parse.
   * @see Integer#parseInt(String)
   */
  private static int toint(String s) throws NumberFormatException {
    return Integer.parseInt(s);
  }

  /**
   * A convenience method for converting a {@link String} to an <code>float</code>.
   *
   * @param s {@link String} to parse.
   * @return the converted <code>float</code>.
   * @throws NumberFormatException If the {@link String} failed to parse.
   * @see Float#parseFloat(String)
   */
  private static float tofloat(String s) throws NumberFormatException {
    return Float.parseFloat(s);
  }

  /**
   * A convenience method for converting a {@link String} to an <code>long</code>.
   *
   * @param s {@link String} to parse.
   * @return the converted <code>long</code>.
   * @throws NumberFormatException If the {@link String} failed to parse.
   * @see Long#parseLong(String)
   */
  private static long tolong(String s) throws NumberFormatException {
    return Long.parseLong(s);
  }

  /**
   * A convenience method for converting a {@link String} to an <code>double</code>.
   *
   * @param s {@link String} to parse.
   * @return the converted <code>double</code>.
   * @throws NumberFormatException If the {@link String} failed to parse.
   * @see Double#parseDouble(String)
   */
  private static double todouble(String s) throws NumberFormatException {
    return Double.parseDouble(s);
  }

  /**
   * A convenience method for converting a {@link String} to an <code>boolean</code>.
   *
   * @param s {@link String} to parse.
   * @return the converted <code>boolean</code>.
   * @see Boolean#parseBoolean(String)
   */
  private static boolean tobool(String s) {
    return Boolean.parseBoolean(s);
  }

  /**
   * Creates a {@link LabelNode} with a custom offset.
   *
   * @param offset the offset for the {@link Label}.
   * @return a custom-offset {@link LabelNode}
   * @see CustomLabel
   * @see CustomLabel#getOffset()
   * @see org.objectweb.asm.Label#getOffset()
   */
  public static LabelNode getLabelNode(int offset) {
    return new LabelNode(new CustomLabel(offset));
  }


  // TODO javadocs for these *shudder*
  public static boolean isAbstract(int access) {
    return (access & ACC_ABSTRACT) != 0;
  }

  public static boolean isFinal(int access) {
    return (access & ACC_FINAL) != 0;
  }

  public static boolean isStatic(int access) {
    return (access & ACC_STATIC) != 0;
  }

  public static boolean isNative(int access) {
    return (access & ACC_NATIVE) != 0;
  }

  public static boolean isSynthetic(int access) {
    return (access & ACC_SYNTHETIC) != 0;
  }

  public static boolean isSynchronized(int access) {
    return (access & ACC_SYNCHRONIZED) != 0;
  }

  public static boolean isEnum(int access) {
    return (access & ACC_ENUM) != 0;
  }

  public static boolean isBridge(int access) {
    return (access & ACC_BRIDGE) != 0;
  }

  public static boolean isVolatile(int access) {
    return (access & ACC_VOLATILE) != 0;
  }

  public static boolean isDeprecated(int access) {
    return (access & ACC_DEPRECATED) != 0;
  }

  public static boolean isMandated(int access) {
    return (access & ACC_MANDATED) != 0;
  }

  public static boolean isInterface(int access) {
    return (access & ACC_INTERFACE) != 0;
  }

  public static boolean isAnnotated(int access) {
    return (access & ACC_ANNOTATION) != 0;
  }

  public static boolean isPrivate(int access) {
    return (access & ACC_PRIVATE) != 0;
  }

  public static boolean isPublic(int access) {
    return (access & ACC_PUBLIC) != 0;
  }

  public static boolean isProtected(int access) {
    return (access & ACC_PROTECTED) != 0;
  }

  public static boolean isStrictFP(int access) {
    return (access & ACC_STRICT) != 0;
  }

  public static boolean isSuper(int access) { // archaic, no longer used as of some Java 1.7 update
    return (access & ACC_SUPER) != 0;
  }

  public static boolean isVarArgs(int access) {
    return (access & ACC_VARARGS) != 0;
  }

  public static boolean isTransient(int access) {
    return (access & ACC_TRANSIENT) != 0;
  }

  public static int removeFlag(int flag, int flags) {
    return flags & ~flag;
  }

  public static int addFlag(int flag, int flags) {
    return flags | flag;
  }

  public static int getLabelOffset(Label label, InsnList instructions) {
    try {
      return label.getOffset();
    } catch (Exception e) {
      ListIterator<AbstractInsnNode> li = instructions.iterator();
      AbstractInsnNode ain = li.next();
      for (int i = 0; li.hasNext(); ain = li.next(), i++) {
        if (ain instanceof LabelNode) {
          if (((LabelNode) ain).getLabel() == label) {
            return i;
          } else {
            i--; // this fixes the issue where it counted labels as instructions.
            continue;
          }
        }
      }
      return -1;
    }
  }
}
TOP

Related Classes of nf.co.haxter.util.BytecodeUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.