Пример #1
1
  public static void renameClassNode(final String oldName, final String newName) {
    for (ClassNode c : BytecodeViewer.getLoadedClasses()) {
      for (Object oo : c.innerClasses) {
        InnerClassNode innerClassNode = (InnerClassNode) oo;
        if (innerClassNode.innerName != null && innerClassNode.innerName.equals(oldName)) {
          innerClassNode.innerName = newName;
        }
        if (innerClassNode.name.equals(oldName)) {
          innerClassNode.name = newName;
        }
        if (innerClassNode.outerName != null && innerClassNode.outerName.equals(oldName)) {
          innerClassNode.outerName = newName;
        }
      }

      if (c.signature != null) c.signature = c.signature.replace(oldName, newName);

      if (c.superName.equals(oldName)) {
        c.superName = newName;
      }
      for (Object o : c.fields.toArray()) {
        FieldNode f = (FieldNode) o;
        f.desc = f.desc.replace(oldName, newName);
      }
      for (Object o : c.interfaces.toArray()) {
        String truxerLipton = (String) o;
        truxerLipton = truxerLipton.replace(oldName, newName);
      }
      for (Object o : c.methods.toArray()) {
        MethodNode m = (MethodNode) o;

        if (m.localVariables != null) {
          for (LocalVariableNode node : (List<LocalVariableNode>) m.localVariables) {
            node.desc = node.desc.replace(oldName, newName);
          }
        }

        if (m.signature != null) m.signature = m.signature.replace(oldName, newName);

        for (int i = 0; i < m.exceptions.size(); i++) {
          if (m.exceptions.get(i).equals(oldName)) m.exceptions.set(i, newName);
        }

        for (AbstractInsnNode i : m.instructions.toArray()) {
          if (i instanceof TypeInsnNode) {
            TypeInsnNode t = (TypeInsnNode) i;
            if (t.desc.equals(oldName)) {
              t.desc = newName;
            }
          }
          if (i instanceof MethodInsnNode) {
            MethodInsnNode mi = (MethodInsnNode) i;
            if (mi.owner.equals(oldName)) mi.owner = newName;
            mi.desc = mi.desc.replace(oldName, newName);
          }
          if (i instanceof FieldInsnNode) {
            FieldInsnNode fi = (FieldInsnNode) i;
            if (fi.owner.equals(oldName)) fi.owner = newName;
            fi.desc = fi.desc.replace(oldName, newName);
          }
        }
      }
    }
  }
  @Override
  public byte[] transform(String name, String transformedName, byte[] bytes) {
    if (transformedName.equals("net.minecraft.block.BlockDynamicLiquid")
        && CoreLoadingPlugin.util.getBoolean("FiniteWater", false)) {
      ClassReader reader = new ClassReader(bytes);
      ClassNode node = new ClassNode();
      reader.accept(node, 0);
      InsnList getSmallestFlowDecay = new InsnList();

      getSmallestFlowDecay.add(new VarInsnNode(ALOAD, 0));
      getSmallestFlowDecay.add(new InsnNode(ICONST_0));
      getSmallestFlowDecay.add(
          new FieldInsnNode(
              PUTFIELD, "net/minecraft/block/BlockDynamicLiquid", "field_149815_a", "I"));

      for (MethodNode method : node.methods)
        if ("func_149810_a"
            .equals(
                FMLDeobfuscatingRemapper.INSTANCE.mapMethodName(name, method.name, method.desc)))
          method.instructions.insertBefore(method.instructions.getFirst(), getSmallestFlowDecay);

      ClassWriter writer = new ClassWriter(0);
      node.accept(writer);
      return writer.toByteArray();
    }

    return bytes;
  }
  private static void transformIfNeccessary(File file) throws IOException {
    InputStream is = new FileInputStream(file);
    ClassNode cn;
    try {
      ClassReader cr = new ClassReader(is);
      cn = new ClassNode();
      cr.accept(cn, 0);
    } finally {
      is.close();
    }

    if (!isAlreadyTransformed(cn) && isAnnotationPresent(cn)) {
      System.out.println("Transforming file " + file);
      ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
      ClassVisitor ca = new CheckClassAdapter(cw);
      ClassVisitor cv = new PropertyChangeSupportAdapter(ca);
      cn.accept(cv);
      FileOutputStream os = new FileOutputStream(file);
      try {
        os.write(cw.toByteArray());
      } finally {
        os.close();
      }
    }
  }
 @Override
 public byte[] transform(String className, String transformedClassName, byte[] bytes) {
   String methodName;
   if (className.equals(OBF_CLASS)) {
     methodName = SRG_METHOD;
   } else if (className.equals(MCP_CLASS)) {
     methodName = MCP_METHOD;
   } else {
     return bytes;
   }
   ClassNode classNode = new ClassNode();
   ClassReader classReader = new ClassReader(bytes);
   classReader.accept(classNode, 0);
   for (MethodNode method : classNode.methods) {
     if (method.name.equals(methodName) && method.desc.equals(METHOD_DESC)) {
       logger.info("CraftingTweaks will now patch {} in {}...", methodName, className);
       MethodNode mn = new MethodNode();
       Label notClicked = new Label();
       // mn.visitMethodInsn(Opcodes.INVOKESTATIC, "org/lwjgl/input/Mouse", "getEventButtonState",
       // "()Z", false);
       // mn.visitJumpInsn(Opcodes.IFEQ, notClicked); // if getEventButtonState false, continue
       // after
       mn.visitVarInsn(Opcodes.ILOAD, 1); // push mouseX
       mn.visitVarInsn(Opcodes.ILOAD, 2); // push mouseY
       mn.visitVarInsn(Opcodes.ILOAD, 3); // push button
       mn.visitMethodInsn(
           Opcodes.INVOKESTATIC,
           "net/blay09/mods/craftingtweaks/CraftingTweaks",
           "onGuiClick",
           "(III)Z",
           false); // call onGuiClick
       mn.visitJumpInsn(Opcodes.IFEQ, notClicked); // if onGuiClick false, continue after
       mn.visitInsn(Opcodes.RETURN); // otherwise stop here
       mn.visitLabel(notClicked); // continue from here
       AbstractInsnNode insertAfter = null;
       for (int i = 0; i < method.instructions.size(); i++) {
         AbstractInsnNode node = method.instructions.get(i);
         if (node instanceof VarInsnNode) {
           if (node.getOpcode() == Opcodes.ISTORE && ((VarInsnNode) node).var == 3) { // ISTORE 3
             insertAfter = node;
             break;
           }
         }
       }
       if (insertAfter != null) {
         method.instructions.insert(insertAfter, mn.instructions);
         logger.info("CraftingTweaks successfully patched {} in {}!", methodName, className);
       } else {
         logger.warn(
             "CraftingTweaks failed to patch {0}::{1} ({2} not found) - transfering into crafting grids will not work!",
             className, methodName, "ISTORE 3");
       }
     }
   }
   ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
   classNode.accept(writer);
   return writer.toByteArray();
 }
Пример #5
0
  @Override
  public byte[] transform(String name, String transformedName, byte[] basicClass) {
    if (!"net.minecraft.item.ItemStack".equals(name)) return basicClass;
    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(basicClass);
    classReader.accept(classNode, 0);

    FieldNode itemField = null;
    for (FieldNode f : classNode.fields) {
      if (ITEM_TYPE.equals(f.desc) && itemField == null) {
        itemField = f;
      } else if (ITEM_TYPE.equals(f.desc)) {
        throw new RuntimeException("Error processing ItemStack - found a duplicate Item field");
      }
    }
    if (itemField == null) {
      throw new RuntimeException(
          "Error processing ItemStack - no Item field declared (is the code somehow obfuscated?)");
    }

    MethodNode getItemMethod = null;
    for (MethodNode m : classNode.methods) {
      if (GETITEM_DESC.equals(m.desc) && getItemMethod == null) {
        getItemMethod = m;
      } else if (GETITEM_DESC.equals(m.desc)) {
        throw new RuntimeException("Error processing ItemStack - duplicate getItem method found");
      }
    }
    if (getItemMethod == null) {
      throw new RuntimeException(
          "Error processing ItemStack - no getItem method found (is the code somehow obfuscated?)");
    }

    for (MethodNode m : classNode.methods) {
      for (ListIterator<AbstractInsnNode> it = m.instructions.iterator(); it.hasNext(); ) {
        AbstractInsnNode insnNode = it.next();
        if (insnNode.getType() == AbstractInsnNode.FIELD_INSN) {
          FieldInsnNode fi = (FieldInsnNode) insnNode;
          if (itemField.name.equals(fi.name) && fi.getOpcode() == Opcodes.GETFIELD) {
            it.remove();
            MethodInsnNode replace =
                new MethodInsnNode(
                    Opcodes.INVOKEVIRTUAL,
                    "net/minecraft/item/ItemStack",
                    getItemMethod.name,
                    getItemMethod.desc,
                    false);
            it.add(replace);
          }
        }
      }
    }
    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    classNode.accept(writer);
    return writer.toByteArray();
  }
Пример #6
0
  private byte[] transformEntitySheep(byte[] bytes) {
    System.out.println("Transforming EntitySheep...");
    ClassNode cn = new ClassNode();
    ClassReader cr = new ClassReader(bytes);
    cr.accept(cn, 0);

    Iterator<MethodNode> methods = cn.methods.iterator();
    while (methods.hasNext()) {
      MethodNode m = methods.next();

      if (m.name.equals(names.get("entitySheep_setColour_func"))
          && m.desc.equals(names.get("entitySheep_setColour_desc"))) {
        System.out.println("Found target method: " + m.name + m.desc + "! Inserting call...");

        for (int idx = 0; idx < m.instructions.size(); idx++) {
          if (m.instructions.get(idx).getOpcode() == Opcodes.ISTORE) {
            System.out.println("Found ISTORE at index " + idx + ", inserting code afterwards...");
            idx++; // AFTERwards, not before ;)

            InsnList toAdd = new InsnList();

            // to mark the end of the code
            LabelNode lmmnode = new LabelNode(new Label());
            // load this
            toAdd.add(new VarInsnNode(Opcodes.ALOAD, 0));
            // new fleece colour
            toAdd.add(new VarInsnNode(Opcodes.ILOAD, 1));
            // old fleece colour
            toAdd.add(new VarInsnNode(Opcodes.ILOAD, 2));
            toAdd.add(
                new MethodInsnNode(
                    Opcodes.INVOKESTATIC,
                    "keepcalm/mods/events/ForgeEventHelper",
                    "onSheepDye",
                    "(L" + names.get("entitySheep_javaName") + ";II)Z"));
            LabelNode endIf = new LabelNode(new Label());
            toAdd.add(new JumpInsnNode(Opcodes.IFEQ, endIf));
            toAdd.add(new InsnNode(Opcodes.RETURN));
            toAdd.add(endIf);
            toAdd.add(lmmnode);

            m.instructions.insertBefore(m.instructions.get(idx), toAdd);
            break;
          }
        }
      }
    }

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    cn.accept(cw);
    return cw.toByteArray();
  }
  protected byte[] transformClass(byte[] bytes, String clssname) {
    InputStream is = getClass().getResourceAsStream("/" + clssname.replace('.', '/') + ".class");

    ClassReader orig = null;
    try {
      ClassReader crRepl = new ClassReader(is);
      ClassNode cnRepl = new ClassNode(Opcodes.ASM4);
      crRepl.accept(cnRepl, ClassReader.SKIP_FRAMES);

      ClassReader crOrig = new ClassReader(bytes);
      ClassNode cnOrig = new ClassNode(Opcodes.ASM4);
      crOrig.accept(cnOrig, ClassReader.SKIP_FRAMES);

      for (Object ofnRepl : cnRepl.fields) {
        FieldNode fnRepl = (FieldNode) ofnRepl;

        if (hasReplaceAnnotation(fnRepl.visibleAnnotations)) {
          FieldNode fnOrig = findField(cnOrig.fields, fnRepl);
          if (fnOrig != null) {
            cnOrig.fields.remove(fnOrig);
            cnOrig.fields.add(cnOrig.fields.size(), scrubField(cnOrig, cnRepl, fnRepl));
          }
        } else if (hasAddAnnotation(fnRepl.visibleAnnotations)) {
          cnOrig.fields.add(cnOrig.fields.size(), scrubField(cnOrig, cnRepl, fnRepl));
        }
      }

      for (Object omnRepl : cnRepl.methods) {
        MethodNode mnRepl = (MethodNode) omnRepl;

        if (hasReplaceAnnotation(mnRepl.visibleAnnotations)) {
          MethodNode mnOrig = findMethod(cnOrig.methods, mnRepl);
          if (mnOrig != null) {
            cnOrig.methods.remove(mnOrig);
            cnOrig.methods.add(cnOrig.methods.size(), scrubMethod(cnOrig, cnRepl, mnRepl));
          }
        } else if (hasAddAnnotation(mnRepl.visibleAnnotations)) {
          cnOrig.methods.add(cnOrig.methods.size() + 1, scrubMethod(cnOrig, cnRepl, mnRepl));
        }
      }

      ClassWriter cwNew = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
      cnOrig.accept(cwNew);
      return cwNew.toByteArray();
    } catch (IOException e) {
      e.printStackTrace(); // To change body of catch statement use File | Settings | File
      // Templates.
    }

    return bytes;
  }
Пример #8
0
  public byte[] transformCreeper(byte[] bytes) {
    ClassNode cn = new ClassNode();
    ClassReader cr = new ClassReader(bytes);
    cr.accept(cn, 0);

    // System.out.println("Transforming EntityCreeper...");

    Iterator<MethodNode> methods = cn.methods.iterator();

    while (methods.hasNext()) {
      MethodNode m = methods.next();

      // System.out.println(m.name + m.desc + " vs " + names.get("entityCreeper_onUpdate_func") +
      // names.get("entityCreeper_onUpdate_desc"));
      if (m.name.equals(names.get("entityCreeper_onUpdate_func"))
          && m.desc.equals(names.get("entityCreeper_onUpdate_desc"))) {
        for (int i = m.instructions.size() - 1; i >= 0; i--) {
          if (m.instructions.get(i).getOpcode() == Opcodes.IFNE) {
            System.out.println("Found insertion point! inserting code!");
            i++;

            InsnList insns = new InsnList();

            insns.add(new VarInsnNode(Opcodes.ALOAD, 0));
            insns.add(
                new MethodInsnNode(
                    Opcodes.INVOKESTATIC,
                    "keepcalm/mods/events/ForgeEventHelper",
                    "onCreeperExplode",
                    "(L" + names.get("entityCreeper_javaName") + ";)Z"));
            LabelNode endIf = new LabelNode(new Label());
            insns.add(new JumpInsnNode(Opcodes.IFEQ, endIf));
            // insns.add(new VarInsnNode(Opcodes.ALOAD, 0));
            // insns.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
            // names.get("entityCreeper_javaName"), names.get("entityCreeper_setDead_func"),
            // names.get("entityCreeper_setDead_desc")));
            insns.add(new InsnNode(Opcodes.RETURN));
            insns.add(endIf);
            insns.add(new LabelNode(new Label()));

            m.instructions.insertBefore(m.instructions.get(i), insns);
            break;
          }
        }
      }
    }
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    cn.accept(cw);
    return cw.toByteArray();
  }
Пример #9
0
 public static byte[] getBytesFromClassNode(ClassNode c) {
   ClassWriter w = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
   c.accept(w);
   byte[] b = w.toByteArray();
   SquidAPIPlugin.LOGGER.info("Successfully transformed " + c.name.replace("/", "."), ".");
   return b;
 }
Пример #10
0
  private void createAddMessage(ClassNode cn) {
    Pattern p =
        new PatternBuilder()
            .add(
                new InstructionElement(ALOAD),
                new LdcElement(new LdcInsnNode("")),
                new InstructionElement(ALOAD),
                new InstructionElement(INVOKEVIRTUAL))
            .build();

    MethodInsnNode ebola1 = null;

    for (MethodNode mn : cn.methods) {
      if (!p.contains(mn.instructions)) continue;

      int offset = p.getOffset(mn.instructions);

      ebola1 = (MethodInsnNode) mn.instructions.get(offset + 3);
    }

    {
      MethodVisitor mv =
          cn.visitMethod(ACC_PUBLIC, "addChatMessage", "(Ljava/lang/String;)V", null, null);
      mv.visitVarInsn(ALOAD, 0);
      mv.visitLdcInsn("");
      mv.visitVarInsn(ALOAD, 1);
      mv.visitMethodInsn(INVOKEVIRTUAL, ebola1.owner, ebola1.name, ebola1.desc, ebola1.itf);
      mv.visitInsn(RETURN);
      mv.visitEnd();
    }
  }
  private static byte[] transform(int index, byte[] classBeingTransformed, boolean isObfuscated) {
    LOG.info("Transforming: " + classesBeingTransformed[index]);
    try {
      ClassNode classNode = new ClassNode();
      ClassReader classReader = new ClassReader(classBeingTransformed);
      classReader.accept(classNode, 0);

      switch (index) {
        case 0:
          transformBiblioFramingChest(classNode, isObfuscated);
          break;
      }

      ClassWriter classWriter =
          new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
      classNode.accept(classWriter);
      return classWriter.toByteArray();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return classBeingTransformed;
  }
Пример #12
0
  private byte[] transformNetServerHandler(byte[] bytes) {
    ClassNode cn = new ClassNode();
    ClassReader cr = new ClassReader(bytes);
    cr.accept(cn, 0);

    Iterator<MethodNode> methods = cn.methods.iterator();
    while (methods.hasNext()) {
      MethodNode m = methods.next();

      if (m.name.equals(names.get("netServerHandler_handleFlying_func"))
          && m.desc.equals(names.get("netServerHandler_handleFlying_desc"))) {
        System.out.println("Found target method: " + m.name + m.desc + "! Inserting code...");

        InsnList toInsert = new InsnList();
        toInsert.add(new VarInsnNode(Opcodes.ALOAD, 1));
        toInsert.add(new VarInsnNode(Opcodes.ALOAD, 0));
        toInsert.add(
            new MethodInsnNode(
                Opcodes.INVOKESTATIC,
                "keepcalm/mods/events/ForgeEventHelper",
                "onPlayerMove",
                "(L"
                    + names.get("packet10Flying_javaName")
                    + ";L"
                    + names.get("netServerHandler_javaName")
                    + ";)Z"));
        LabelNode endIf = new LabelNode(new Label());
        toInsert.add(new JumpInsnNode(Opcodes.IFEQ, endIf));
        toInsert.add(new InsnNode(Opcodes.RETURN));
        toInsert.add(endIf);
        toInsert.add(new LabelNode(new Label()));
        m.instructions.insert(toInsert);
      }
    }

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    cn.accept(cw);
    return cw.toByteArray();
  }
Пример #13
0
 public byte[] finish(String name, String transformedName) {
   if (currentClass == null) return null;
   ClassWriter cw =
       new ClassWriter(
           0 /*ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS*/); // compute everything from
                                                                         // scratch
   currentClass.accept(cw);
   currentClass = null;
   byte[] ret = cw.toByteArray();
   ret =
       temporaryFixOfStuff(
           name, transformedName, ret); // ret = fixSide(name, transformedName, ret);
   return ret;
 }
Пример #14
0
  @Override
  public byte[] transform(String name, byte[] bytes) {
    if (bytes == null || name.equals("com.nexus.network.packets.Packet")) {
      return bytes;
    }
    ClassReader cr = new ClassReader(bytes);
    ClassNode classNode = new ClassNode();
    cr.accept(classNode, 0);

    try {
      if (transformPacket(classNode)) {
        ClassWriter cw = new ClassWriter(COMPUTE_MAXS | COMPUTE_FRAMES);
        classNode.accept(cw);
        return cw.toByteArray();
      }
      return bytes;
    } catch (ClassCastException e) {

    } catch (Exception e) {
      e.printStackTrace();
    }
    return bytes;
  }
  private void fixFieldAccessInMethods() {
    List<MethodNode> methods = new LinkedList<MethodNode>();

    for (MethodNode methodNode : (List<MethodNode>) classNode.methods) {
      MethodMetadata methodMetadata =
          classMetadata.getMethodMetadata(methodNode.name, methodNode.desc);

      if (methodMetadata.isTransactional()) {
        methodNode = fixMethod(methodNode);
      }

      methods.add(methodNode);
    }

    classNode.methods = methods;
  }
  private void fixFields() {
    List<FieldNode> fields = new LinkedList<FieldNode>();
    for (FieldNode fieldNode : (List<FieldNode>) classNode.fields) {
      FieldMetadata fieldMetadata = classMetadata.getFieldMetadata(fieldNode.name);
      if (fieldMetadata.hasFieldGranularity()) {
        String referenceDesc = findReferenceDesc(fieldNode.desc);

        FieldNode fixedFieldNode =
            new FieldNode(
                ACC_SYNTHETIC + ACC_FINAL + ACC_PUBLIC,
                fieldNode.name,
                referenceDesc,
                null, // signature
                null // value
                );

        fields.add(fixedFieldNode);
      } else {
        fields.add(fieldNode);
      }
    }

    classNode.fields = fields;
  }
  // 下記の想定で実装されています。
  // EntityLiving.class の doRenderLiving の先頭に
  // tutorial/test.class の passTestRender(EntityLiving, double, double, double)メソッドの呼び出しを追加する。
  private byte[] hookOnItemRightClick(String className, byte[] bytes) {
    // ASMで、bytesに格納されたクラスファイルを解析します。
    ClassNode cnode = new ClassNode();
    ClassReader reader = new ClassReader(bytes);
    reader.accept(cnode, 0);

    // 改変対象のメソッド名です
    String targetMethodName = "onItemRightClick";
    String targetMethodNameSRG = "func_77659_a";

    // 改変対象メソッドの戻り値型および、引数型をあらわします ※1
    String targetMethoddesc =
        "(Lnet/minecraft/item/ItemStack;Lnet/minecraft/world/World;Lnet/minecraft/entity/player/EntityPlayer;)Lnet/minecraft/item/ItemStack;";
    String targetMethoddescSRG =
        "(Lnet/minecraft/item/ItemStack;Lnet/minecraft/world/World;Lnet/minecraft/entity/player/EntityPlayer;)Lnet/minecraft/item/ItemStack;";

    // 対象のメソッドを検索取得します。
    MethodNode mnode = null;

    String mdesc = null;

    for (MethodNode curMnode : cnode.methods) {

      String mName =
          FMLDeobfuscatingRemapper.INSTANCE.mapMethodName(className, curMnode.name, curMnode.desc);
      String mdName = FMLDeobfuscatingRemapper.INSTANCE.mapMethodDesc(curMnode.desc);
      // System.out.println("[ " + mName + " : " + curMnode.name + " ]  [ " + mdName + " : " +
      // curMnode.desc);
      if ((targetMethodName.equals(curMnode.name) && targetMethoddesc.equals(curMnode.desc))
          || (targetMethodNameSRG.equals(mName) && targetMethoddescSRG.equals(mdName))) {
        mnode = curMnode;
        mdesc = curMnode.desc;
        break;
      }
    }

    if (mnode != null) {

      InsnList overrideList = new InsnList();

      // メソッドコールを、バイトコードであらわした例です。

      overrideList.add(new VarInsnNode(ALOAD, 1));
      overrideList.add(new VarInsnNode(ALOAD, 2));
      overrideList.add(new VarInsnNode(ALOAD, 3));
      overrideList.add(
          new MethodInsnNode(
              INVOKESTATIC,
              "shift/sextiarysector/asm/vanilla/BottleMethod",
              "onBottleRightClick",
              mdesc,
              false));
      overrideList.add(new InsnNode(ARETURN));

      // mnode.instructions.get(1)で、対象のメソッドの先頭を取得
      // mnode.instructions.insertで、指定した位置にバイトコードを挿入します。
      mnode.instructions.insert(mnode.instructions.get(1), overrideList);

      // mnode.maxLocals = 4;

      // 改変したクラスファイルをバイト列に書き出します
      ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
      cnode.accept(cw);
      bytes = cw.toByteArray();

      System.out.println("bbbb");
    }

    return bytes;
  }
Пример #18
0
 public static byte[] getBytesFromClassNodeNoMsg(ClassNode c) {
   ClassWriter w = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
   c.accept(w);
   byte[] b = w.toByteArray();
   return b;
 }
Пример #19
0
  @Override
  public byte[] transform(String name, String transformedName, byte[] bytes) {
    if (bytes == null) {
      return null;
    }

    if (DEBUG) {
      FMLRelaunchLog.fine("Considering all methods and fields on %s (%s)\n", name, transformedName);
    }
    if (!modifiers.containsKey(name)) {
      return bytes;
    }

    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(bytes);
    classReader.accept(classNode, 0);

    Collection<Modifier> mods = modifiers.get(name);
    for (Modifier m : mods) {
      if (m.modifyClassVisibility) {
        classNode.access = getFixedAccess(classNode.access, m);
        if (DEBUG) {
          System.out.println(
              String.format(
                  "Class: %s %s -> %s", name, toBinary(m.oldAccess), toBinary(m.newAccess)));
        }
        continue;
      }
      if (m.desc.isEmpty()) {
        for (FieldNode n : classNode.fields) {
          if (n.name.equals(m.name) || m.name.equals("*")) {
            n.access = getFixedAccess(n.access, m);
            if (DEBUG) {
              System.out.println(
                  String.format(
                      "Field: %s.%s %s -> %s",
                      name, n.name, toBinary(m.oldAccess), toBinary(m.newAccess)));
            }

            if (!m.name.equals("*")) {
              break;
            }
          }
        }
      } else {
        for (MethodNode n : classNode.methods) {
          if ((n.name.equals(m.name) && n.desc.equals(m.desc)) || m.name.equals("*")) {
            n.access = getFixedAccess(n.access, m);
            if (DEBUG) {
              System.out.println(
                  String.format(
                      "Method: %s.%s%s %s -> %s",
                      name, n.name, n.desc, toBinary(m.oldAccess), toBinary(m.newAccess)));
            }

            if (!m.name.equals("*")) {
              break;
            }
          }
        }
      }
    }

    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    classNode.accept(writer);
    return writer.toByteArray();
  }
 private synchronized void load() {
   if (LOAD_LOCAL) {
     System.out.println("Loading local gamepack.");
     final File gamepack = new File("gamepack.jar");
     if (!gamepack.exists()) {
       System.out.println("Unable to load local gamepack.");
       System.out.println();
       return;
     }
     System.out.println("Successfully loaded local gamepack.");
     System.out.println();
     System.out.println("Loading classes.");
     try {
       final JarFile jar = new JarFile(gamepack);
       final Enumeration<JarEntry> entries = jar.entries();
       int loaded = 0;
       while (entries.hasMoreElements()) {
         final JarEntry entry = entries.nextElement();
         String name = entry.getName();
         if (!name.endsWith(".class") || name.contains("/")) {
           continue;
         }
         name = name.substring(0, name.length() - 6);
         final ClassReader cr = new ClassReader(jar.getInputStream(entry));
         final ClassNode cn = new ClassNode();
         cr.accept(cn, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
         classes.put(name, cn);
         loaded++;
       }
       System.out.println("Successfully loaded " + loaded + " classes.");
     } catch (final IOException e) {
       System.out.println("Unable to load classes.");
     }
   } else {
     final byte[] gamepack = getGamepack();
     if (gamepack == null) {
       return;
     }
     System.out.println();
     final Map<String, byte[]> innerpack = decryptGamepack(gamepack);
     if (innerpack == null) {
       return;
     }
     System.out.println();
     System.out.println("Loading classes.");
     int loaded = 0;
     for (final Map.Entry<String, byte[]> entry : innerpack.entrySet()) {
       final String name = entry.getKey();
       final ClassReader cr = new ClassReader(entry.getValue());
       final ClassNode cn = new ClassNode();
       cr.accept(cn, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
       classes.put(name, cn);
       loaded++;
     }
     System.out.println("Successfully loaded " + loaded + " classes.");
     try {
       final FileOutputStream fos = new FileOutputStream(new File("gamepack.jar"));
       final JarOutputStream jos = new JarOutputStream(fos);
       for (final Map.Entry<String, ClassNode> entry : classes.entrySet()) {
         final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
         final ClassNode cn = entry.getValue();
         cn.accept(cw);
         jos.putNextEntry(new JarEntry(cn.name + ".class"));
         jos.write(cw.toByteArray());
         jos.closeEntry();
       }
       jos.close();
       fos.close();
     } catch (final Exception ignored) {
     }
   }
   System.out.println();
 }
  public byte[] patchOnUpdate(String name, byte[] bytes, boolean obfuscated) {
    RMLog.info("[EntityPlayer] [onUpdate] Patching", true);
    String targetMethodName = "";

    if (obfuscated == true) targetMethodName = "h";
    else targetMethodName = "onUpdate";
    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(bytes);
    classReader.accept(classNode, 0);

    Iterator<MethodNode> methods = classNode.methods.iterator();
    while (methods.hasNext()) {
      MethodNode method = methods.next();
      int invok_index = -1;
      if ((method.name.equals(targetMethodName) && method.desc.equals("()V"))) {
        AbstractInsnNode currentNode = null;
        AbstractInsnNode targetNode = null;

        Iterator<AbstractInsnNode> iter = method.instructions.iterator();

        int index = -1;

        int GETFIELD_COUNT = 0;
        while (iter.hasNext()) {
          index++;
          currentNode = iter.next();
          if (currentNode.getOpcode() == Opcodes.GETFIELD) {
            GETFIELD_COUNT++;
            if (GETFIELD_COUNT == 13) {
              targetNode = currentNode;
              invok_index = index;
              break;
            }
          }
        }
        if (targetNode == null || invok_index == -1) {
          RMLog.info(
              "[EntityPlayer] Did not find all necessary target nodes! ABANDON CLASS!", true);
          return bytes;
        }
        /*
         * mv.visitLineNumber(305, l19);
         * mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
         * mv.visitVarInsn(ALOAD, 0);
         * -- mv.visitFieldInsn(GETFIELD, "net/minecraft/entity/player/EntityPlayer", "worldObj", "Lnet/minecraft/world/World;");
         * mv.visitFieldInsn(GETFIELD, "net/minecraft/world/World", "isRemote", "Z");
         * Label l21 = new Label();
         * mv.visitJumpInsn(IFNE, l21);
         */
        @SuppressWarnings("unused")
        AbstractInsnNode p1, p2, p3;
        p1 = method.instructions.get(invok_index - 1); // mv.visitVarInsn(ALOAD, 0);
        p2 = method.instructions.get(invok_index); // mv.visitFieldInsn(GETFIELD,
        // "net/minecraft/entity/player/EntityPlayer", "worldObj",
        // "Lnet/minecraft/world/World;");
        p3 =
            method.instructions.get(
                invok_index
                    + 1); // mv.visitFieldInsn(GETFIELD, "net/minecraft/world/World", "isRemote",
        // "Z");

        // method.instructions.remove(p1);
        // method.instructions.remove(p2);
        // method.instructions.remove(p3);

        MethodInsnNode m1 =
            new MethodInsnNode(
                Opcodes.INVOKESTATIC,
                "net/roryclaasen/asm/rorysmodcore/transformer/StaticClass",
                "shouldWakeUp",
                "(Lnet/minecraft/entity/player/EntityPlayer;)Z",
                false);

        method.instructions.set(p2, m1);
        method.instructions.remove(p3);
        break;
      }
    }
    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    classNode.accept(writer);
    return writer.toByteArray();
  }
Пример #22
0
 public void visitEnd() {
   classNode.accept(cv);
 }
Пример #23
0
  @SuppressWarnings("unchecked")
  private void modify(ClassNode node) {
    if (!mappings.containsKey(node.name)) return;
    JSONObject object = mappings.get(node.name);

    String identity = (String) object.get("identity");
    String parentOverride = (String) object.get("parent_override");
    if (parentOverride != null && !parentOverride.equals("null")) {
      node.superName = parentOverride;
      if (node.superName.contains("Canvas")) {
        for (MethodNode mn : (List<MethodNode>) node.methods) {
          if (mn.name.equals("<init>")) {
            for (AbstractInsnNode insn : mn.instructions.toArray()) {
              if (insn.getOpcode() == Opcodes.INVOKESPECIAL) {
                MethodInsnNode min = (MethodInsnNode) insn;
                if (min.owner.contains("Canvas")) {
                  min.owner = node.superName;
                }
              }
            }
          }
        }
      }

      // System.out.println("\t"+node.name+" parent changed to "+parentOverride);
    }

    JSONArray interfaces = (JSONArray) object.get("interfaces");
    for (int i = 0; i < interfaces.size(); i++) {
      if (!node.interfaces.contains(interfaces.get(i))) {
        // System.out.println("\tAdded interface " + interfaces.get(i) + " to " + identity + " (" +
        // node.name + ")");

        node.interfaces.add(interfaces.get(i));
      }
    }

    // remove interfaces not specified
    for (int i = 0; i < node.interfaces.size(); i++) {
      if (!interfaces.contains(node.interfaces.get(i))) {
        // System.out.println("\tRemoved interface " + node.interfaces.get(i) + " from " + identity
        // + " (" + node.name + ")");
        node.interfaces.remove(i);
      }
    }

    if (identity.equals("Renderable")) {

      for (MethodNode mn : (List<MethodNode>) node.methods) {
        if ((mn.access & Opcodes.ACC_STATIC) != 0) {
          continue;
        }

        if (!mn.desc.endsWith("V")) {
          continue;
        }

        InstructionSearcher searcher =
            new InstructionSearcher(mn.instructions, 0, Opcodes.INVOKEVIRTUAL, Opcodes.ASTORE);

        if (searcher.match()) {
          InstructionSearcher search =
              new InstructionSearcher(mn.instructions, 0, Opcodes.INVOKEVIRTUAL);
          AbstractInsnNode[] primMatches = searcher.getMatches().get(0);
          if (search.match()) {
            AbstractInsnNode[] matches = search.getMatches().get(1);

            VarInsnNode var = new VarInsnNode(Opcodes.ALOAD, 0);
            VarInsnNode var2 =
                new VarInsnNode(
                    Opcodes.ALOAD, ((VarInsnNode) primMatches[primMatches.length - 1]).var);

            mn.instructions.insert(matches[matches.length - 1], var);
            mn.instructions.insert(var, var2);
            mn.instructions.insert(
                var2,
                new MethodInsnNode(
                    Opcodes.INVOKESTATIC,
                    "org/vinsert/bot/script/callback/ModelCallback",
                    "callback",
                    "(Lorg/vinsert/insertion/IRenderable;Lorg/vinsert/insertion/IModel;)V"));

            // System.out.println("\tInserted model callback to "+node.name+"."+mn.name);
          }
        }
      }
    }

    //		if (identity.equals("GameObject")) {
    //			for (MethodNode mn : (List<MethodNode>) node.methods) {
    //				if ((mn.access & Opcodes.ACC_STATIC) != 0) {
    //					continue;
    //				}
    //
    //				if (mn.desc.endsWith("V")) {
    //					continue;
    //				}
    //
    //				InstructionSearcher searcher = new InstructionSearcher(mn.instructions, 10, Opcodes.LDC,
    // Opcodes.IMUL, Opcodes.LDC, Opcodes.INVOKEVIRTUAL, Opcodes.ARETURN);
    //
    //				if (searcher.match()) {
    //
    //					AbstractInsnNode[] matches = searcher.getMatches().get(0);
    //
    //					VarInsnNode var = new VarInsnNode(Opcodes.ALOAD, 0);
    //					VarInsnNode var2 = new VarInsnNode(Opcodes.ALOAD, ((VarInsnNode) matches[matches.length -
    // 1]).var);
    ////
    //					mn.instructions.insert(mn.instructions.get(mn.instructions.size() - 1), var);
    //					mn.instructions.insert(var, var2);
    //					mn.instructions.insert(var2, new MethodInsnNode(Opcodes.INVOKESTATIC,
    // "com/hijackrs/bot/script/callback/ModelCallback", "callback",
    // "(Lcom/hijackrs/insertion/Renderable;Lcom/hijackrs/insertion/Model;)V"));
    //					System.out.println("\tInserted model callback to "+node.name+"."+mn.name);
    //				}
    //			}
    //		}

    JSONArray mappings = (JSONArray) object.get("mappings");
    for (int i = 0; i < mappings.size(); i++) {
      JSONObject entry = (JSONObject) mappings.get(i);
      String parent = (String) entry.get("parent");
      String name = (String) entry.get("name");
      String getterName = (String) entry.get("identity");
      String signature = (String) entry.get("signature");
      String fieldSignature = (String) entry.get("field_signature");
      boolean isStatic = (Boolean) entry.get("static");
      int opLoad = ((Number) entry.get("op_load")).intValue();
      int opReturn = ((Number) entry.get("op_return")).intValue();
      int modBits = ((Number) entry.get("mod_bits")).intValue();
      int modDirect = ((Number) entry.get("mod_value")).intValue();
      boolean modInverse = (Boolean) entry.get("mod_inverse");

      insert(
          node,
          parent,
          name,
          getterName,
          signature,
          fieldSignature,
          isStatic,
          opLoad,
          opReturn,
          modBits,
          modDirect,
          modInverse);
    }
  }
  @Override
  public byte[] transform(String name, String transformedName, byte[] basicClass) {
    if (!name.startsWith("lc.")) return basicClass;

    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(basicClass);
    classReader.accept(classNode, 0);
    List<FieldNode> fields = classNode.fields;
    if (fields == null || fields.size() == 0) return basicClass;
    HashMap<String, String> fieldToClazzMap = new HashMap<String, String>();
    Iterator<FieldNode> iq = fields.iterator();
    while (iq.hasNext()) {
      FieldNode field = iq.next();
      AnnotationNode hintNode = ASMAssist.findAnnotation(field, "Llc/api/defs/HintProvider;");
      if (hintNode != null) {
        Side theSide = FMLCommonHandler.instance().getSide();
        if (theSide == Side.CLIENT) {
          String className = ASMAssist.findValue(hintNode, "clientClass");
          if (className != null) fieldToClazzMap.put(field.name, className.replace(".", "/"));
        } else {
          String className = ASMAssist.findValue(hintNode, "serverClass");
          if (className != null) fieldToClazzMap.put(field.name, className.replace(".", "/"));
        }
      }
    }

    if (fieldToClazzMap.size() != 0) {
      LCLog.debug("Adding %s hint field initializer mappings.", fieldToClazzMap.size());
      Iterator<MethodNode> methods = classNode.methods.iterator();
      MethodNode initMethod = null;
      while (methods.hasNext()) {
        MethodNode method = methods.next();
        if (method.name.equals("<init>")) {
          initMethod = method;
          break;
        }
      }

      AbstractInsnNode lastInsn = null;
      if (initMethod == null) {
        initMethod = new MethodNode(Opcodes.ACC_PUBLIC, "<init>", "()V", "", null);
        lastInsn = new InsnNode(Opcodes.RETURN);
        initMethod.instructions.add(lastInsn);
      } else
        for (Iterator<AbstractInsnNode> insns = initMethod.instructions.iterator();
            insns.hasNext(); ) {
          AbstractInsnNode node = insns.next();
          if (node.getOpcode() == Opcodes.RETURN) lastInsn = node;
        }

      for (Entry<String, String> mapping : fieldToClazzMap.entrySet()) {
        LCLog.debug(
            "Adding mapping for hint %s to class initializer %s.",
            mapping.getKey(), mapping.getValue());
        initMethod.instructions.insertBefore(lastInsn, new VarInsnNode(Opcodes.ALOAD, 0));
        initMethod.instructions.insertBefore(
            lastInsn, new TypeInsnNode(Opcodes.NEW, mapping.getValue()));
        initMethod.instructions.insertBefore(lastInsn, new InsnNode(Opcodes.DUP));
        initMethod.instructions.insertBefore(
            lastInsn,
            new MethodInsnNode(Opcodes.INVOKESPECIAL, mapping.getValue(), "<init>", "()V", false));
        initMethod.instructions.insertBefore(
            lastInsn,
            new FieldInsnNode(
                Opcodes.PUTFIELD,
                name.replace(".", "/"),
                mapping.getKey(),
                "Llc/common/IHintProvider;"));
      }

      if (initMethod.maxStack < fieldToClazzMap.size() * 4)
        initMethod.maxStack += fieldToClazzMap.size() * 4;
    }

    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    classNode.accept(writer);
    return writer.toByteArray();
  }
Пример #25
0
  private byte[] transformLightningBolt(byte[] bytes) {
    ClassNode cn = new ClassNode();
    ClassReader cr = new ClassReader(bytes);
    cr.accept(cn, 0);

    Iterator<MethodNode> methods = cn.methods.iterator();
    while (methods.hasNext()) {
      MethodNode m = methods.next();
      if (m.name.equals("<init>")) {
        System.out.println("Found constructor in EntityLightningBolt, searching for landmarks...");
        AbstractInsnNode mark1 = null;
        AbstractInsnNode mark2 = null;
        AbstractInsnNode firstEndIf = null;
        AbstractInsnNode secondEndIf = null;

        InsnList insns1 = new InsnList();
        insns1.add(new VarInsnNode(Opcodes.ALOAD, 0));
        insns1.add(new VarInsnNode(Opcodes.ALOAD, 1));
        insns1.add(new VarInsnNode(Opcodes.ILOAD, 8));
        insns1.add(new VarInsnNode(Opcodes.ILOAD, 9));
        insns1.add(new VarInsnNode(Opcodes.ILOAD, 10));
        insns1.add(
            new MethodInsnNode(
                Opcodes.INVOKESTATIC,
                "keepcalm/mods/events/ForgeEventHelper",
                "onLightningStrike",
                "(L"
                    + names.get("entityLightningBolt_javaName")
                    + ";L"
                    + names.get("world_javaName")
                    + ";III)Z"));
        LabelNode endIf1 = new LabelNode(new Label());
        insns1.add(new JumpInsnNode(Opcodes.IFNE, endIf1));

        InsnList insns2 = new InsnList();
        insns1.add(new InsnNode(Opcodes.ACONST_NULL));
        insns2.add(new VarInsnNode(Opcodes.ALOAD, 1));
        insns2.add(new VarInsnNode(Opcodes.ILOAD, 9));
        insns2.add(new VarInsnNode(Opcodes.ILOAD, 10));
        insns2.add(new VarInsnNode(Opcodes.ILOAD, 11));
        insns2.add(
            new MethodInsnNode(
                Opcodes.INVOKESTATIC,
                "keepcalm/mods/events/ForgeEventHelper",
                "onLightningStrike",
                "(L"
                    + names.get("entityLightningBolt_javaName")
                    + ";L"
                    + names.get("world_javaName")
                    + ";III)Z"));
        LabelNode endIf2 = new LabelNode(new Label());
        insns2.add(new JumpInsnNode(Opcodes.IFNE, endIf2));
        boolean firstInvokeV = false;

        for (int i = 0; i < m.instructions.size(); i++) {

          if (m.instructions.get(i).getOpcode() == Opcodes.IFEQ) {
            if (mark1 != null) mark2 = m.instructions.get(i).getNext();
            else mark1 = m.instructions.get(i).getNext();
          }

          if (m.instructions.get(i).getOpcode() == Opcodes.INVOKEVIRTUAL
              && !firstInvokeV
              && mark1 != null) {
            firstEndIf = m.instructions.get(i).getNext();
          } else if (m.instructions.get(i).getOpcode() == Opcodes.INVOKEVIRTUAL
              && mark2 != null
              && firstInvokeV) {
            secondEndIf = m.instructions.get(i).getNext();
          }
        }
        m.instructions.insertBefore(mark1, insns1);
        m.instructions.insertBefore(firstEndIf, endIf1);
        m.instructions.insertBefore(mark2, insns2);
        m.instructions.insertBefore(secondEndIf, endIf2);
      }
    }

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    cn.accept(cw);
    return cw.toByteArray();
  }
Пример #26
0
  // too lazy to deobfuscate all network/chat stuff, use info from method
  // calls to create new send message function
  private void createSendMessage(ClassNode cn) {
    Pattern p =
        new PatternBuilder()
            .add(
                new InstructionElement(INVOKESTATIC),
                new AnyElement(),
                new LdcElement(new LdcInsnNode("Chat")),
                new InstructionElement(INVOKEVIRTUAL))
            .build();

    MethodInsnNode newBuilder = null;
    MethodInsnNode setChatText = null;
    MethodInsnNode ebola1 = null;
    MethodInsnNode ebola2 = null;
    MethodInsnNode ebola3 = null;
    MethodInsnNode ebola4 = null;
    MethodInsnNode ebola5 = null;
    MethodInsnNode ebola6 = null;
    MethodInsnNode ebola7 = null;

    for (MethodNode mn : cn.methods) {
      if (!p.contains(mn.instructions)) continue;

      int offset = p.getOffset(mn.instructions);

      newBuilder = (MethodInsnNode) mn.instructions.get(offset - 9); // newbuilder
      // then var insn of parameter, ldc or w/e
      setChatText = (MethodInsnNode) mn.instructions.get(offset - 7); // setchattext
      ebola1 = (MethodInsnNode) mn.instructions.get(offset - 6); // U a
      ebola2 = (MethodInsnNode) mn.instructions.get(offset - 5); // U p
      ebola3 = (MethodInsnNode) mn.instructions.get(offset - 4); // Player
      // r
      ebola4 = (MethodInsnNode) mn.instructions.get(offset - 3); // setMapID
      ebola5 = (MethodInsnNode) mn.instructions.get(offset - 2); // build
      // store that crap
      ebola6 = (MethodInsnNode) mn.instructions.get(offset); // i e
      // load crap again
      // LDC "Chat"
      ebola7 = (MethodInsnNode) mn.instructions.get(offset + 3); // i a
    }

    {
      MethodVisitor mv =
          cn.visitMethod(ACC_PUBLIC, "sendChatMessage", "(Ljava/lang/String;)V", null, null);
      mv.visitMethodInsn(
          INVOKESTATIC, newBuilder.owner, newBuilder.name, newBuilder.desc, newBuilder.itf);
      mv.visitVarInsn(ALOAD, 1);
      mv.visitMethodInsn(
          INVOKEVIRTUAL, setChatText.owner, setChatText.name, setChatText.desc, setChatText.itf);
      mv.visitMethodInsn(INVOKESTATIC, ebola1.owner, ebola1.name, ebola1.desc, ebola1.itf);
      mv.visitMethodInsn(INVOKEVIRTUAL, ebola2.owner, ebola2.name, ebola2.desc, ebola2.itf);
      mv.visitMethodInsn(INVOKEVIRTUAL, ebola3.owner, ebola3.name, ebola3.desc, ebola3.itf);
      mv.visitMethodInsn(INVOKEVIRTUAL, ebola4.owner, ebola4.name, ebola4.desc, ebola4.itf);
      mv.visitMethodInsn(INVOKEVIRTUAL, ebola5.owner, ebola5.name, ebola5.desc, ebola5.itf);
      mv.visitVarInsn(ASTORE, 2);
      mv.visitMethodInsn(INVOKESTATIC, ebola6.owner, ebola6.name, ebola6.desc, ebola6.itf);
      mv.visitVarInsn(ALOAD, 2);
      mv.visitLdcInsn("Chat");
      mv.visitMethodInsn(INVOKEVIRTUAL, ebola7.owner, ebola7.name, ebola7.desc, ebola7.itf);
      mv.visitInsn(RETURN);
      mv.visitMaxs(2, 2);
      mv.visitEnd();
    }
  }
 @Override
 public byte[] transform(
     ClassLoader loader,
     String className,
     Class<?> classBeingRedefined,
     ProtectionDomain protectionDomain,
     byte[] classfileBuffer)
     throws IllegalClassFormatException {
   if (classBeingRedefined != null) {
     return null;
   }
   if (className.startsWith("java/")
       || className.startsWith("javax/")
       || className.startsWith("sun/")) {
     return null;
   }
   List<MethodNode> coroutineMethodsInCurrentClass;
   boolean debug = generateDebugCode;
   boolean print = printCode;
   boolean verify = runVerification;
   boolean outputBin = generateBinaryOutput;
   boolean asmComputeFrames = overrideFrames;
   if (!detectCoroutineClasses) {
     int classnameIndex = Arrays.binarySearch(coroutineEnabledClassnames, className);
     if (classnameIndex < 0) {
       // search package
       String packageName = className;
       int indexOfSlash;
       while ((indexOfSlash = packageName.lastIndexOf('/')) != -1) {
         packageName = packageName.substring(0, indexOfSlash);
         classnameIndex = Arrays.binarySearch(coroutineEnabledClassnames, packageName);
         if (classnameIndex >= 0) {
           break;
         }
       }
       if (classnameIndex < 0) return null;
     }
     debug = debugMode[classnameIndex];
     print = printMode[classnameIndex];
     verify = verifyMode[classnameIndex];
     outputBin = outputBinMode[classnameIndex];
     asmComputeFrames = overrideFramesMode[classnameIndex];
   }
   boolean log = logger.isLoggable(Level.FINEST);
   if (log) {
     logger.finest(className + ": Analyzing");
   }
   ClassReader asmClassReader = new ClassReader(classfileBuffer);
   ClassNode cn = new ClassNode();
   asmClassReader.accept(cn, debug ? 0 : ClassReader.SKIP_DEBUG);
   ClassAnalyzer analyzer = new ClassAnalyzer(cn);
   analyzer.analyze();
   coroutineMethodsInCurrentClass = analyzer.getCoroutineMethods();
   if (coroutineMethodsInCurrentClass.isEmpty()) {
     return null;
   }
   if (log) {
     logger.finest(
         className
             + ": Instrumenting coroutines "
             + methodNodeListToString(coroutineMethodsInCurrentClass));
   }
   ClassWriter asmClassWriter =
       new ClassWriter(
           (asmComputeFrames ? ClassWriter.COMPUTE_FRAMES : 0) | ClassWriter.COMPUTE_MAXS);
   ClassVisitor cv = asmClassWriter;
   byte[] instrumentedClassContents;
   try {
     if (print) {
       try {
         cv = createTracer(className, cv);
       } catch (FileNotFoundException e) {
         throw new CoroutineGenerationException("Unable to write trace file ", e);
       }
     }
     new ClassTransformer(cn, coroutineMethodsInCurrentClass, debug).transform();
     cn.accept(cv);
     instrumentedClassContents = asmClassWriter.toByteArray();
     if (verify) {
       verifyClass(className, new ClassReader(instrumentedClassContents), print);
     }
     if (outputBin) {
       dumpClass(className + "Instrumented", instrumentedClassContents);
     }
   } catch (IllegalStateException e) {
     logger.log(Level.WARNING, "Verification failed", e);
     return null;
   } catch (IllegalArgumentException e) {
     logger.log(Level.WARNING, "Verification failed", e);
     return null;
   } catch (CoroutineGenerationException e) {
     logger.warning(e.getMessage());
     return null;
   } catch (Throwable t) {
     logger.log(
         Level.SEVERE,
         "Coroutine generation ended abruptly. This may be a bug in the package itself. Details below:",
         t);
     return null;
   }
   return instrumentedClassContents;
 }
Пример #28
0
  @Override
  public byte[] transform(String name, String transformedName, byte[] bytes) {
    if (bytes == null) {
      return null;
    }
    boolean makeAllPublic = FMLDeobfuscatingRemapper.INSTANCE.isRemappedClass(name);

    if (DEBUG) {
      FMLRelaunchLog.fine(
          "Considering all methods and fields on %s (%s): %b\n",
          name, transformedName, makeAllPublic);
    }
    if (!makeAllPublic && !modifiers.containsKey(name)) {
      return bytes;
    }

    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(bytes);
    classReader.accept(classNode, 0);

    if (makeAllPublic) {
      // class
      Modifier m = new Modifier();
      m.targetAccess = ACC_PUBLIC;
      m.modifyClassVisibility = true;
      modifiers.put(name, m);
      // fields
      m = new Modifier();
      m.targetAccess = ACC_PUBLIC;
      m.name = "*";
      modifiers.put(name, m);
      // methods
      m = new Modifier();
      m.targetAccess = ACC_PUBLIC;
      m.name = "*";
      m.desc = "<dummy>";
      modifiers.put(name, m);
      if (DEBUG) {
        System.out.printf("Injected all public modifiers for %s (%s)\n", name, transformedName);
      }
    }

    Collection<Modifier> mods = modifiers.get(name);
    for (Modifier m : mods) {
      if (m.modifyClassVisibility) {
        classNode.access = getFixedAccess(classNode.access, m);
        if (DEBUG) {
          System.out.println(
              String.format(
                  "Class: %s %s -> %s", name, toBinary(m.oldAccess), toBinary(m.newAccess)));
        }
        continue;
      }
      if (m.desc.isEmpty()) {
        for (FieldNode n : classNode.fields) {
          if (n.name.equals(m.name) || m.name.equals("*")) {
            n.access = getFixedAccess(n.access, m);
            if (DEBUG) {
              System.out.println(
                  String.format(
                      "Field: %s.%s %s -> %s",
                      name, n.name, toBinary(m.oldAccess), toBinary(m.newAccess)));
            }

            if (!m.name.equals("*")) {
              break;
            }
          }
        }
      } else {
        for (MethodNode n : classNode.methods) {
          if ((n.name.equals(m.name) && n.desc.equals(m.desc)) || m.name.equals("*")) {
            n.access = getFixedAccess(n.access, m);
            if (DEBUG) {
              System.out.println(
                  String.format(
                      "Method: %s.%s%s %s -> %s",
                      name, n.name, n.desc, toBinary(m.oldAccess), toBinary(m.newAccess)));
            }

            if (!m.name.equals("*")) {
              break;
            }
          }
        }
      }
    }

    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    classNode.accept(writer);
    return writer.toByteArray();
  }