/**
   * Chain together a ClassReader than will read the given class and a ClassWriter to write out a
   * new class with an adapter in the middle to add annotations
   *
   * @param fromName the name of the class we're coming from
   */
  private static void adaptClass(String fromName) {
    if (VERBOSE) System.out.println("Adding annotations to class: " + fromName);

    // gets an input stream to read the bytecode of the class
    String resource = fromName.replace('.', '/') + ".class";
    InputStream is = BootstrapClassLoader.getBootstrapClassLoader().getResourceAsStream(resource);
    byte[] b;

    // adapts the class on the fly
    try {
      ClassReader cr = new ClassReader(is);
      ClassWriter cw = new ClassWriter(0);
      ClassVisitor cv = new AddAnnotationClassAdapter(cw, fromName);
      cr.accept(cv, 0);
      b = cw.toByteArray();
    } catch (Exception e) {
      throw new Error("Couldn't find class " + fromName + " (" + resource + ")", e);
    }

    // store the adapted class on disk
    try {
      File file = new File(destinationDir + resource);
      new File(file.getParent()).mkdirs(); // ensure we have a directory to write to
      FileOutputStream fos = new FileOutputStream(file);
      fos.write(b);
      fos.close();
    } catch (Exception e) {
      throw new Error("Error writing to " + destinationDir + resource + " to disk", e);
    }
  }
 private String getFieldType(String owner, String name) {
   if (fieldDescriptions.containsKey(owner)) {
     return fieldDescriptions.get(owner).get(name);
   }
   synchronized (fieldDescriptions) {
     try {
       byte[] classBytes =
           ClassPatchManager.INSTANCE.getPatchedResource(
               owner, map(owner).replace('/', '.'), classLoader);
       if (classBytes == null) {
         return null;
       }
       ClassReader cr = new ClassReader(classBytes);
       ClassNode classNode = new ClassNode();
       cr.accept(
           classNode, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
       Map<String, String> resMap = Maps.newHashMap();
       for (FieldNode fieldNode : (List<FieldNode>) classNode.fields) {
         resMap.put(fieldNode.name, fieldNode.desc);
       }
       fieldDescriptions.put(owner, resMap);
       return resMap.get(name);
     } catch (IOException e) {
       FMLRelaunchLog.log(
           Level.ERROR, e, "A critical exception occured reading a class file %s", owner);
     }
     return null;
   }
 }
Example #3
0
 public static void main(String[] args) throws IOException {
   InputStream in = App.class.getResourceAsStream("App.class");
   ClassPrinter cp = new ClassPrinter();
   ClassReader cr = new ClassReader(in);
   cr.accept(cp, 0);
   in.close();
 }
Example #4
0
  public static void main(String[] args)
      throws NoSuchMethodException, SecurityException, IllegalArgumentException,
          InvocationTargetException {
    try {
      ClassReader classReader = new ClassReader("com/asm/Before_Demo1");
      ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);

      ClassAdapter ca = new AopClassAdapter(cw);

      classReader.accept(ca, ClassReader.SKIP_DEBUG);

      byte[] byteArray = cw.toByteArray();

      MyClassLoader myClassLoader = new MyClassLoader();
      Class<?> clazz = myClassLoader.myDefineClass(byteArray, "com.asm.Before_Demo1");
      Method method = clazz.getMethod("sayHello");
      method.invoke(clazz.newInstance());

    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (InstantiationException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
  @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;
  }
Example #6
0
  public synchronized Map<String, String> getImportedClasses(String name)
      throws ClassNotFoundException {

    if (dontBother.contains(name)) {
      throw new ClassNotFoundException(name);
    }
    try {
      ClassReader reader = new ClassReader(getResourceAsStream(name.replace('.', '/') + ".class"));
      PMDASMVisitor asmVisitor = new PMDASMVisitor();
      reader.accept(asmVisitor, 0);

      List<String> inner = asmVisitor.getInnerClasses();
      if (inner != null && !inner.isEmpty()) {
        inner = new ArrayList<String>(inner); // to avoid ConcurrentModificationException
        for (String str : inner) {
          reader = new ClassReader(getResourceAsStream(str.replace('.', '/') + ".class"));
          reader.accept(asmVisitor, 0);
        }
      }
      return asmVisitor.getPackages();
    } catch (IOException e) {
      dontBother.add(name);
      throw new ClassNotFoundException(name, e);
    }
  }
 @Override
 public boolean apply(MethodRef input) {
   String owner = input.getOwner();
   if (owner.charAt(0) == '[') {
     owner = "java/lang/Object";
   }
   Map<Key, Boolean> map = this.map.get(owner);
   if (map == null) {
     try (InputStream in = loader.getResourceAsStream(owner + ".class")) {
       if (in == null) {
         throw new IllegalArgumentException("Object type " + owner + " not found");
       }
       ClassReader reader = new ClassReader(in);
       map = new HashMap<>();
       ClassAdapter adapter = new ClassAdapter(map);
       reader.accept(adapter, SKIP_DEBUG | SKIP_FRAMES);
     } catch (IOException e) {
       throw new IllegalArgumentException(e);
     }
     Map<Key, Boolean> prevMap = this.map.putIfAbsent(owner, map);
     if (prevMap != null) {
       map = prevMap;
     }
   }
   String name = input.getName();
   String desc = input.getDesc();
   Boolean suspendable = map.get(new Key(name, desc));
   if (suspendable == null) {
     throw new IllegalArgumentException("Method " + owner + '.' + name + desc + " not found");
   }
   return suspendable;
 }
Example #8
0
  protected Set<Class> processFileUrl(URL url, String basepath, Class clazz) throws IOException {
    Set<Class> set = new HashSet<Class>();
    String urlBase = url.getFile();
    // We can't URLDecoder.decode(path) since some encoded chars are allowed on file uris
    urlBase = urlBase.replaceAll("%20", " ");
    File dir = new File(urlBase);
    if (!dir.isDirectory()) {
      logger.warn("Cannot process File URL: " + url + ". Path is not a directory");
      return set;
    }

    Collection<File> files = FileUtils.listFiles(new File(urlBase), new String[] {"class"}, true);
    for (File file : files) {
      try {
        InputStream classStream = new FileInputStream(file);
        ClassReader reader = new ClosableClassReader(classStream);

        ClassScanner visitor = getScanner(clazz);
        reader.accept(visitor, 0);
        if (visitor.isMatch()) {
          Class c = loadClass(visitor.getClassName());
          if (c != null) {
            set.add(c);
          }
        }
      } catch (IOException e) {
        if (logger.isDebugEnabled()) {
          Throwable t = ExceptionHelper.getRootException(e);
          logger.debug(String.format("%s: caused by: %s", e.toString(), t.toString()));
        }
      }
    }
    return set;
  }
  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();
      }
    }
  }
  /**
   * Determine imports for a class given as a String resource. This method doesn't do any search for
   * the enclosing/inner classes as it considers that these should be handled at a higher level.
   *
   * <p>The returned set contains the packages in string format (i.e. java.io)
   *
   * @param className
   * @param resource
   * @return
   */
  private Set determineImportsForClass(String className, Resource resource) {
    Assert.notNull(resource, "a not-null class is required");
    DependencyVisitor visitor = new DependencyVisitor();

    boolean trace = logger.isTraceEnabled();

    ClassReader reader;

    try {
      if (trace) logger.trace("Visiting class " + className);
      reader = new ClassReader(resource.getInputStream());
    } catch (Exception ex) {
      throw (RuntimeException)
          new IllegalArgumentException("Cannot read class " + className).initCause(ex);
    }
    reader.accept(visitor, false);

    // convert from / to . format
    Set originalPackages = visitor.getPackages();
    Set pkgs = new LinkedHashSet(originalPackages.size());

    for (Iterator iterator = originalPackages.iterator(); iterator.hasNext(); ) {
      String pkg = (String) iterator.next();
      pkgs.add(pkg.replace('/', '.'));
    }
    return pkgs;
  }
Example #11
0
  protected Set<Class> processJarUrl(URL url, String basepath, Class clazz) throws IOException {
    Set<Class> set = new HashSet<Class>();
    String path = url.getFile().substring(5, url.getFile().indexOf("!"));
    JarFile jar = new JarFile(path);

    for (Enumeration entries = jar.entries(); entries.hasMoreElements(); ) {
      JarEntry entry = (JarEntry) entries.nextElement();
      if (entry.getName().startsWith(basepath) && entry.getName().endsWith(".class")) {
        try {
          String name = entry.getName();
          // Ignore anonymous
          // TODO RM what about the other anonymous classes like $2, $3 ?
          if (name.contains("$1")) {
            continue;
          }
          URL classURL = classLoader.getResource(name);
          ClassReader reader = new ClassReader(classURL.openStream());
          ClassScanner visitor = getScanner(clazz);
          reader.accept(visitor, 0);
          if (visitor.isMatch()) {
            Class c = loadClass(visitor.getClassName());
            if (c != null) {
              set.add(c);
            }
          }
        } catch (Exception e) {
          if (logger.isDebugEnabled()) {
            Throwable t = ExceptionHelper.getRootException(e);
            logger.debug(String.format("%s: caused by: %s", e.toString(), t.toString()));
          }
        }
      }
    }
    return set;
  }
Example #12
0
 public static void dumpClass(String className, byte[] data) {
   System.out.println("DUMP OF CLASS: " + className);
   ClassReader cr = new ClassReader(data);
   ClassVisitor cv = new TraceClassVisitor(null, new Textifier(), new PrintWriter(System.out));
   cr.accept(cv, ClassReader.SKIP_FRAMES);
   System.out.println("=================");
 }
Example #13
0
  @Test
  public void testMethodClass() throws IOException {
    ClassReader reader = new ClassReader("TestFiles.TestJavaCodeASMParsing");
    ClassVisitor visitor = new ClassDecorationVisitor(Opcodes.ASM5);
    ClassVisitor fieldVisitor = new ClassFieldVisitor(Opcodes.ASM5, visitor);
    ClassVisitor methodVisitor = new ClassMethodVisitor(Opcodes.ASM5, fieldVisitor);

    reader.accept(methodVisitor, ClassReader.EXPAND_FRAMES);

    Map<String, MethodClass> methods = new HashMap<String, MethodClass>();
    methods = ((ClassMethodVisitor) methodVisitor).getMethodsInfoCollection();
    ArrayList<String> methodsName = new ArrayList<String>();
    methodsName.add("add");
    methodsName.add("println");
    methodsName.add("getA");
    methodsName.add("getB");
    methodsName.add("getC");
    methodsName.add("print");

    assertEquals(methodsName.size(), methods.keySet().size() - 1);
    for (String k : methods.keySet()) {
      if (!methods.get(k).getName().contains("init")) {
        assertTrue(methodsName.contains(methods.get(k).getName()));
        methodsName.remove(methods.get(k).getName());
      }
    }
  }
  @Override
  public void parse(
      final BytecodeArtifact bytecodeArtifact, final IPathResolver directoryResolver) {
    assert null != bytecodeArtifact
        : "Parameter 'bytecodeArtifact' of method 'parse' must not be null";

    /** (1) */
    final ClassReader cr = new ClassReader(bytecodeArtifact.getBytesOriginal());

    /** (2) */
    // cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
    final ClassWriter cw = new ClassWriter(cr, 0);

    /** (3) */
    final ASMClassInstrumentor ca = constructSelf(cw);

    /** (4) */
    cr.accept(ca, ClassReader.EXPAND_FRAMES);

    assert null != ca : "'ca' of method 'parse' must not be null";
    assert null != cw : "'cw' of method 'parse' must not be null";

    final String fileAbsolutePath = bytecodeArtifact.absolutePath();
    this.benchmark.addBytecodeArtificatAnalysed(
        ca.className,
        cw.toByteArray(),
        fileAbsolutePath,
        directoryResolver,
        bytecodeArtifact.isClassFile(),
        this.isInterface);
  }
Example #15
0
  private boolean readClass(String clazz) throws IOException {
    ClassReader cr = new ClassReader(new FileInputStream(clazz));
    ClassNode ca =
        new ClassNode() {
          public void visitEnd() {
            // accept(cv);
          }
        };
    cr.accept(new CheckClassAdapter(ca), true);
    boolean failed = false;

    List methods = ca.methods;
    for (int i = 0; i < methods.size(); ++i) {
      MethodNode method = (MethodNode) methods.get(i);
      if (method.instructions.size() > 0) {
        Analyzer a = new Analyzer(new SimpleVerifier());
        try {
          a.analyze(ca.name, method);
          continue;
        } catch (Exception e) {
          e.printStackTrace();
        }
        final Frame[] frames = a.getFrames();

        if (!failed) {
          failed = true;
          log("verifying of class " + clazz + " failed");
        }
        if (verbose) log(method.name + method.desc);
        TraceMethodVisitor cv =
            new TraceMethodVisitor(null) {
              public void visitMaxs(int maxStack, int maxLocals) {
                StringBuffer buffer = new StringBuffer();
                for (int i = 0; i < text.size(); ++i) {
                  String s = frames[i] == null ? "null" : frames[i].toString();
                  while (s.length() < maxStack + maxLocals + 1) {
                    s += " ";
                  }
                  buffer.append(Integer.toString(i + 100000).substring(1));
                  buffer.append(" ");
                  buffer.append(s);
                  buffer.append(" : ");
                  buffer.append(text.get(i));
                }
                if (verbose) log(buffer.toString());
              }
            };
        for (int j = 0; j < method.instructions.size(); ++j) {
          Object insn = method.instructions.get(j);
          if (insn instanceof AbstractInsnNode) {
            ((AbstractInsnNode) insn).accept(cv);
          } else {
            cv.visitLabel((Label) insn);
          }
        }
        cv.visitMaxs(method.maxStack, method.maxLocals);
      }
    }
    return !failed;
  }
  /**
   * For debugging, it's useful to dump the content of the generated classes along with the
   * exception that was generated.
   *
   * <p>However to make it work you need to pull in the org.objectweb.asm.util.TraceClassVisitor
   * class and associated utilities which are found in the ASM source jar. Since we don't want that
   * dependency in the source code, we only put it manually for development and access the
   * TraceClassVisitor via reflection if present.
   *
   * @param t The exception thrown by {@link ClassLoader2#testModifiedInstance()}
   * @param cl2 The {@link ClassLoader2} instance with the generated bytecode.
   * @return Either original {@code t} or a new wrapper {@link Throwable}
   */
  private Throwable dumpGeneratedClass(Throwable t, ClassLoader2 cl2) {
    try {
      // For debugging, dump the bytecode of the class in case of unexpected error
      // if we can find the TraceClassVisitor class.
      Class<?> tcvClass = Class.forName("org.objectweb.asm.util.TraceClassVisitor");

      StringBuilder sb = new StringBuilder();
      sb.append('\n').append(t.getClass().getCanonicalName());
      if (t.getMessage() != null) {
        sb.append(": ").append(t.getMessage());
      }

      for (Entry<String, byte[]> entry : cl2.getByteCode()) {
        String className = entry.getKey();
        byte[] bytes = entry.getValue();

        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        // next 2 lines do: TraceClassVisitor tcv = new TraceClassVisitor(pw);
        Constructor<?> cons = tcvClass.getConstructor(new Class<?>[] {pw.getClass()});
        Object tcv = cons.newInstance(new Object[] {pw});
        ClassReader cr2 = new ClassReader(bytes);
        cr2.accept((ClassVisitor) tcv, 0 /* flags */);

        sb.append("\nBytecode dump: <").append(className).append(">:\n").append(sw.toString());
      }

      // Re-throw exception with new message
      RuntimeException ex = new RuntimeException(sb.toString(), t);
      return ex;
    } catch (Throwable ignore) {
      // In case of problem, just throw the original exception as-is.
      return t;
    }
  }
  public static void main(final String[] args) throws FileNotFoundException, IOException {
    String classFileName = "";
    try {
      classFileName = args[0];
    } catch (Exception exp) {
      die("check class file name (first argument)");
    }

    String methodNameAndDescriptor = "";
    try {
      methodNameAndDescriptor = args[1];
    } catch (Exception exp) {
      die("check method name and descriptor (second argument)");
    }

    final ClassReader cr = new ClassReader(new FileInputStream(classFileName));
    final ClassNode cnode = new ClassNode();

    cr.accept(cnode, 0);

    ControlFlowGraphExtractor control = new ControlFlowGraphExtractor();
    control.flow(cnode, methodNameAndDescriptor);

    System.out.println("\n# READY.");
  }
Example #18
0
  protected Set<Class> processFileUrl(URL url, String basepath, Class clazz) throws IOException {
    Set<Class> set = new HashSet<Class>();
    String urlBase = url.getFile();
    urlBase = URLDecoder.decode(urlBase);

    Collection<File> files = FileUtils.listFiles(new File(urlBase), new String[] {"class"}, true);
    for (File file : files) {
      try {
        ClassReader reader = new ClassReader(new FileInputStream(file));
        ClassScanner visitor = getScanner(clazz);
        reader.accept(visitor, 0);
        if (visitor.isMatch()) {
          Class c = loadClass(visitor.getClassName());
          if (c != null) {
            set.add(c);
          }
        }
      } catch (IOException e) {
        if (logger.isDebugEnabled()) {
          Throwable t = ExceptionHelper.getRootException(e);
          logger.debug(String.format("%s: caused by: %s", e.toString(), t.toString()));
        }
      }
    }
    return set;
  }
 /** {@inheritDoc} */
 public void readClass(InputStream in, VisitorAdapter<ClassVisitorImpl> visitor)
     throws IOException {
   ClassReader reader = new ClassReader(in);
   reader.accept(
       (ClassVisitor) visitor,
       ClassReader.SKIP_CODE & ClassReader.SKIP_DEBUG & ClassReader.SKIP_FRAMES);
 }
  @Override
  public void visit(
      int version,
      int access,
      String name,
      String signature,
      String superName,
      String[] interfaces) {
    if (superName != null) {
      this.nameOfSuper = superName.replaceAll("/", ".");
      try {
        reader = new ClassReader(superName);
        ClassVisitor visitor = new MethodGetterVisitor(Opcodes.ASM5, superMethods);
        reader.accept(visitor, ClassReader.EXPAND_FRAMES);
      } catch (IOException e) {
      }
    }
    if (null != interfaces && interfaces.length == 1) {
      this.interfaces = interfaces;
      try {
        reader = new ClassReader(interfaces[0]);
        ClassVisitor visitor = new MethodGetterVisitor(Opcodes.ASM5, interfaceMethods);
        reader.accept(visitor, ClassReader.EXPAND_FRAMES);
      } catch (IOException e) {
      }
    }

    super.visit(version, access, name, signature, superName, interfaces);
  }
Example #21
0
 public String submitClassFile(byte[] data) {
   ClassNode node = new ClassNode();
   org.objectweb.asm.ClassReader reader = new org.objectweb.asm.ClassReader(data);
   reader.accept(node, 0);
   submitClass(new Parser(new ReferenceCache()).parseClass(node));
   return node.name;
 }
Example #22
0
  private void processEntry(
      final ZipInputStream zis, final ZipEntry ze, final ContentHandlerFactory handlerFactory) {
    ContentHandler handler = handlerFactory.createContentHandler();
    try {

      // if (CODE2ASM.equals(command)) { // read bytecode and process it
      // // with TraceClassVisitor
      // ClassReader cr = new ClassReader(readEntry(zis, ze));
      // cr.accept(new TraceClassVisitor(null, new PrintWriter(os)),
      // false);
      // }

      boolean singleInputDocument = inRepresentation == SINGLE_XML;
      if (inRepresentation == BYTECODE) { // read bytecode and process it
        // with handler
        ClassReader cr = new ClassReader(readEntry(zis, ze));
        cr.accept(new SAXClassAdapter(handler, singleInputDocument), 0);

      } else { // read XML and process it with handler
        XMLReader reader = XMLReaderFactory.createXMLReader();
        reader.setContentHandler(handler);
        reader.parse(
            new InputSource(
                singleInputDocument
                    ? (InputStream) new ProtectedInputStream(zis)
                    : new ByteArrayInputStream(readEntry(zis, ze))));
      }
    } catch (Exception ex) {
      update(ze.getName(), 0);
      update(ex, 0);
    }
  }
    @SuppressWarnings("unused")
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
      try {
        return super.findClass(name);
      } catch (ClassNotFoundException e) {

        byte[] def = mClassDefs.get(name);
        if (def != null) {
          // Load the modified ClassWithNative from its bytes representation.
          return defineClass(name, def, 0, def.length);
        }

        try {
          // Load everything else from the original definition into the new class loader.
          ClassReader cr = new ClassReader(name);
          ClassWriter cw = new ClassWriter(0);
          cr.accept(cw, 0);
          byte[] bytes = cw.toByteArray();
          return defineClass(name, bytes, 0, bytes.length);

        } catch (IOException ioe) {
          throw new RuntimeException(ioe);
        }
      }
    }
Example #24
0
  private static Map<String, Class<?>> defineClasses(
      List<ClassDefinition> classDefinitions, DynamicClassLoader classLoader) {
    ClassInfoLoader classInfoLoader =
        ClassInfoLoader.createClassInfoLoader(classDefinitions, classLoader);

    if (DUMP_BYTE_CODE_TREE) {
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      DumpByteCodeVisitor dumpByteCode = new DumpByteCodeVisitor(new PrintStream(out));
      for (ClassDefinition classDefinition : classDefinitions) {
        dumpByteCode.visitClass(classDefinition);
      }
      System.out.println(new String(out.toByteArray(), StandardCharsets.UTF_8));
    }

    Map<String, byte[]> byteCodes = new LinkedHashMap<>();
    for (ClassDefinition classDefinition : classDefinitions) {
      ClassWriter cw = new SmartClassWriter(classInfoLoader);
      classDefinition.visit(cw);
      byte[] byteCode = cw.toByteArray();
      if (RUN_ASM_VERIFIER) {
        ClassReader reader = new ClassReader(byteCode);
        CheckClassAdapter.verify(reader, classLoader, true, new PrintWriter(System.out));
      }
      byteCodes.put(classDefinition.getType().getJavaClassName(), byteCode);
    }

    String dumpClassPath = DUMP_CLASS_FILES_TO.get();
    if (dumpClassPath != null) {
      for (Map.Entry<String, byte[]> entry : byteCodes.entrySet()) {
        File file =
            new File(
                dumpClassPath,
                ParameterizedType.typeFromJavaClassName(entry.getKey()).getClassName() + ".class");
        try {
          log.debug("ClassFile: " + file.getAbsolutePath());
          Files.createParentDirs(file);
          Files.write(entry.getValue(), file);
        } catch (IOException e) {
          log.error(e, "Failed to write generated class file to: %s" + file.getAbsolutePath());
        }
      }
    }
    if (DUMP_BYTE_CODE_RAW) {
      for (byte[] byteCode : byteCodes.values()) {
        ClassReader classReader = new ClassReader(byteCode);
        classReader.accept(
            new TraceClassVisitor(new PrintWriter(System.err)), ClassReader.SKIP_FRAMES);
      }
    }
    Map<String, Class<?>> classes = classLoader.defineClasses(byteCodes);
    try {
      for (Class<?> clazz : classes.values()) {
        Reflection.initialize(clazz);
      }
    } catch (VerifyError e) {
      throw new RuntimeException(e);
    }
    return classes;
  }
Example #25
0
 private CollectClassData collect(String className) {
   byte[] bytes = getClassBytes(className);
   assertNotNull("Couldn't load bytes for " + className, bytes);
   CollectClassData cv = new CollectClassData();
   ClassReader reader = new ClassReader(bytes);
   reader.accept(cv, 0);
   return cv;
 }
Example #26
0
  private String asmDump(InputStream inputStream) throws IOException {
    ClassReader reader = new ClassReader(inputStream);

    StringWriter writer = new StringWriter();
    reader.accept(new TraceClassVisitor(new PrintWriter(writer)), 0);
    String code = writer.toString().trim();
    return code;
  }
 @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();
 }
  public void MERGE(byte[] bytes) {
    ClassReader cr = new ClassReader(bytes);
    ClassNode merge = new ClassNode();
    cr.accept(
        merge,
        ClassReader.EXPAND_FRAMES | ClassReader.SKIP_FRAMES); // compute everything from scratch

    if (this.currentClass == null) this.currentClass = merge;
  }
  public void run() throws IOException {
    ClassReader cr =
        (inputStream == null)
            ? new ClassConstantsReader(className)
            : new ClassConstantsReader(inputStream);

    ClassVisitor cv = new NameAndSuperClassExtractor();
    cr.accept(cv, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
  }
  @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();
  }