@Override protected void handleClazz(JarFile jarFile, JarOutputStream jos, JarEntry ze, String pathName) { // logger.log(pathName); if (reMapping.containsKey(pathName.substring(0, pathName.length() - 6))) { logger.info("[ClazzReplacer] remove class " + pathName + " form " + jarFile); return; } try { InputStream in = jarFile.getInputStream(ze); ClassReader cr = new ClassReader(in); ClassWriter cw = new ClassWriter(0); RemappingClassAdapter remappingClassAdapter = new RemappingClassAdapter(cw, new SimpleRemapper(reMapping)); cr.accept(remappingClassAdapter, ClassReader.EXPAND_FRAMES); InputStream inputStream = new ByteArrayInputStream(cw.toByteArray()); copyStreamToJar(inputStream, jos, pathName, ze.getTime()); } catch (Throwable e) { System.err.println("[ClazzReplacer] rewrite error > " + pathName); justCopy(jarFile, jos, ze, pathName); } }
static byte[] create(String name, String path) throws IOException { ClassReader reader = new ClassReader(DefaultApplication.class.getClassLoader().getResourceAsStream(DefaultApplication.class.getName().replace('.', '/') + ".class")); String slashName = name.replace('.', '/'); ClassWriter writer = new ClassWriter(0); Remapper remapper = new Remapper() { @Override public String map(String typeName) { if (typeName.equals("org/wildfly/swarm/jaxrs/internal/DefaultApplication")) { return slashName; } return super.map(typeName); } }; RemappingClassAdapter adapter = new RemappingClassAdapter(writer, remapper); reader.accept(adapter, 0); AnnotationVisitor ann = writer.visitAnnotation("Ljavax/ws/rs/ApplicationPath;", true); ann.visit("value", path); ann.visitEnd(); writer.visitEnd(); return writer.toByteArray(); }
static byte[] create() throws IOException { ClassReader reader = new ClassReader(FaviconExceptionMapper.class.getClassLoader().getResourceAsStream(FaviconExceptionMapper.class.getName().replace('.', '/') + ".class")); ClassWriter writer = new ClassWriter(0); Remapper remapper = new Remapper() { @Override public String map(String typeName) { if (typeName.equals("org/wildfly/swarm/jaxrs/internal/FaviconExceptionMapper")) { return "org/wildfly/swarm/generated/FaviconExceptionMapper"; } return super.map(typeName); } }; RemappingClassAdapter adapter = new RemappingClassAdapter(writer, remapper); reader.accept(adapter, 0); writer.visitAnnotation("Ljavax/ws/rs/ext/Provider;", true).visitEnd(); writer.visitEnd(); return writer.toByteArray(); }
public void run() { if (getHooks() == null) return; RefactorMapper mapper = new RefactorMapper(getHooks()); Map<String, ClassNode> refactored = new HashMap<>(); for (ClassNode cn : BytecodeViewer.getLoadedClasses()) { String oldName = cn.name; ClassReader cr = new ClassReader(getClassNodeBytes(cn)); ClassWriter cw = new ClassWriter(cr, 0); RemappingClassAdapter rca = new RemappingClassAdapter(cw, mapper); cr.accept(rca, ClassReader.EXPAND_FRAMES); cr = new ClassReader(cw.toByteArray()); cn = new ClassNode(); cr.accept(cn, 0); refactored.put(oldName, cn); } /*for (Map.Entry<String, ClassNode> factor : refactored.entrySet()) { BytecodeViewer.relocate(factor.getKey(), factor.getValue()); }*/ mapper.printMap(); }
public byte[] rename(byte[] b, Map mappings) throws ClassFormatError { logger.info("Trying to rename class (" + b.length + " bytes)"); try { SimpleRemapper m = new SimpleRemapper(mappings); ClassReader cr = new ClassReader(b); ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES/* | ClassWriter.COMPUTE_MAXS*/); ClassVisitor cv = new RemappingClassAdapter(cw, m); cr.accept(cv, ClassReader.SKIP_DEBUG); return cw.toByteArray(); } catch (Exception e) { logger.error("Failed renaming class: " + e); } return null; }
@Override public byte[] transform(String name, String transformedName, byte[] bytes) { if (bytes == null) { return null; } ClassReader classReader = new ClassReader(bytes); ClassWriter classWriter = new ClassWriter(WRITER_FLAGS); RemappingClassAdapter remapAdapter = new FMLRemappingAdapter(classWriter); classReader.accept(remapAdapter, READER_FLAGS); return classWriter.toByteArray(); }
@Override public byte[] transform(String name, String transformedName, byte[] bytes) { if (bytes == null) { return null; } ClassReader classReader = new ClassReader(bytes); ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS); RemappingClassAdapter remapAdapter = new FMLRemappingAdapter(classWriter); classReader.accept(remapAdapter, ClassReader.EXPAND_FRAMES); return classWriter.toByteArray(); }
private Class<?> loadClassFromFile(final String className) throws IOException { String relativePath = classNameToRelativePath(className); File file = classesRootDirPath.resolve(relativePath).toFile(); byte[] bytes = FileUtils.readFileToByteArray(file); final String newClassName = className + System.currentTimeMillis(); final String newClassInternalName = newClassName.replaceAll("\\.", "/"); final String classInternalName = className.replaceAll("\\.", "/"); ClassReader classReader = new ClassReader(bytes); ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS); RemappingClassAdapter remappingClassAdapter = new RemappingClassAdapter( classWriter, new Remapper() { @Override public String map(String type) { if (classInternalName.equals(type)) { return newClassInternalName; } else { return type; } } }); classReader.accept(remappingClassAdapter, Opcodes.ASM5 | ClassReader.EXPAND_FRAMES); byte[] newBytes = classWriter.toByteArray(); Class<?> klass = defineClass(newClassName, newBytes, 0, newBytes.length); classNameToClass.put(className, klass); return klass; }
/** {@inheritDoc} */ @Override public byte[] loadReplace(InputStream in, final String originalName, final String replaceName) { ClassReader rdr; try { rdr = new ClassReader(in); } catch (IOException e) { throw new RuntimeException(e); } ClassWriter w = new ClassWriter(Opcodes.ASM4); rdr.accept(new RemappingClassAdapter(w, new Remapper() { /** */ String replaceType = replaceName.replace('.', '/'); /** */ String nameType = originalName.replace('.', '/'); @Override public String map(String type) { if (type.equals(replaceType)) return nameType; return type; } }), ClassReader.EXPAND_FRAMES); return w.toByteArray(); }
@Test public void testTransform() throws Exception { ClassRename rule = new ClassRename("java.lang.String", "com.tonicsystems.String"); RemappingClassAdapter t = new RemappingClassAdapter(null, new PackageRemapper(rule)); ClassReader reader = new ClassReader(getClass().getResourceAsStream("/Generics.class")); reader.accept(t, 0); }
private static void _getExternalImports(Set<String> imports, InputStream src,String[] ignores) throws IOException{ final ClassReader reader = new ClassReader(src); final Remapper remapper = new Collector(imports,ignores); final ClassVisitor inner = new EmptyVisitor(); final RemappingClassAdapter visitor = new RemappingClassAdapter(inner, remapper); reader.accept(visitor, 0); }
@Override protected Class<?> findClass(String name) throws ClassNotFoundException { for (Entry<String, String> mapping : remappings.entrySet()) { if (name.equals(mapping.getValue())) { String path = mapping.getKey().replace('.', '/').concat(".class"); try { try (InputStream resource = getResourceAsStream(path)) { ClassReader reader = new ClassReader(resource); ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); ClassVisitor visitor = new RemappingClassAdapter(writer, new Remapper() { @Override public String map(String from) { String to = remappings.get(from.replace('/', '.')); if (to == null) { return from; } else { return to.replace('.', '/'); } } }); reader.accept(visitor, ClassReader.EXPAND_FRAMES); byte[] classBytes = writer.toByteArray(); return defineClass(name, classBytes, 0, classBytes.length); } } catch (IOException e) { throw new ClassNotFoundException("IOException while loading", e); } } } return super.findClass(name); }
private static final ClassNode get(final String name) throws IOException { final InputStream is = ClassVisitor.class.getClassLoader().getResource(name).openStream(); final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final byte[] byteChunk = new byte[4096]; int n; while ((n = is.read(byteChunk)) >= 0) baos.write(byteChunk, 0, n); is.close(); final ClassReader cr = new ClassReader(baos.toByteArray()); final ClassNode cn = new ClassNode(); final RemappingClassAdapter rca = new RemappingClassAdapter(cn, rmp); cr.accept(rca, ClassReader.EXPAND_FRAMES); return cn; }
/** * Loads class from input stream * * @param in * * @throws IOException */ protected void loadClass(InputStream in) throws IOException { ClassReader cr = new ClassReader(in); ClassNode cn = new ClassNode(); RemappingClassAdapter rca = new RemappingClassAdapter(cn, classRemapper); RedirectClassAdapter redir = new RedirectClassAdapter(rca); cr.accept(redir, ClassReader.EXPAND_FRAMES); classNames.add(cn.name.replace('/', '.')); classes.put(cn.name, cn); }
public static MergedClassResult getMergedClass(final ClassSet set, final byte[] precompiledClass, ClassNode generatedClass, final boolean scalarReplace) { if (verifyBytecode) { if (!AsmUtil.isClassBytesOk(logger, "precompiledClass", precompiledClass)) { throw new IllegalStateException("Problem found in precompiledClass"); } if ((generatedClass != null) && !AsmUtil.isClassOk(logger, "generatedClass", generatedClass)) { throw new IllegalStateException("Problem found in generatedClass"); } } /* * Setup adapters for merging, remapping class names and class writing. This is done in * reverse order of how they will be evaluated. */ final RemapClasses re = new RemapClasses(set); try { if (scalarReplace && generatedClass != null) { if (logger.isDebugEnabled()) { AsmUtil.logClass(logger, "generated " + set.generated.dot, generatedClass); } final ClassNode generatedMerged = new ClassNode(); ClassVisitor mergeGenerator = generatedMerged; if (verifyBytecode) { mergeGenerator = new DrillCheckClassAdapter(CompilationConfig.ASM_API_VERSION, new CheckClassVisitorFsm(CompilationConfig.ASM_API_VERSION, generatedMerged), true); } /* * Even though we're effectively transforming-creating a new class in mergeGenerator, * there's no way to pass in ClassWriter.COMPUTE_MAXS, which would save us from having * to figure out stack size increases on our own. That gets handled by the * InstructionModifier (from inside ValueHolderReplacement > ScalarReplacementNode). */ generatedClass.accept(new ValueHolderReplacementVisitor(mergeGenerator, verifyBytecode)); if (verifyBytecode) { if (!AsmUtil.isClassOk(logger, "generatedMerged", generatedMerged)) { throw new IllegalStateException("Problem found with generatedMerged"); } } generatedClass = generatedMerged; } final ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES); ClassVisitor writerVisitor = writer; if (verifyBytecode) { writerVisitor = new DrillCheckClassAdapter(CompilationConfig.ASM_API_VERSION, new CheckClassVisitorFsm(CompilationConfig.ASM_API_VERSION, writerVisitor), true); } ClassVisitor remappingAdapter = new RemappingClassAdapter(writerVisitor, re); if (verifyBytecode) { remappingAdapter = new DrillCheckClassAdapter(CompilationConfig.ASM_API_VERSION, new CheckClassVisitorFsm(CompilationConfig.ASM_API_VERSION, remappingAdapter), true); } ClassVisitor visitor = remappingAdapter; if (generatedClass != null) { visitor = new MergeAdapter(set, remappingAdapter, generatedClass); } ClassReader tReader = new ClassReader(precompiledClass); tReader.accept(visitor, ClassReader.SKIP_FRAMES); byte[] outputClass = writer.toByteArray(); if (logger.isDebugEnabled()) { AsmUtil.logClassFromBytes(logger, "merged " + set.generated.dot, outputClass); } // enable when you want all the generated merged class files to also be written to disk. // Files.write(outputClass, new File(String.format("/src/scratch/drill-generated-classes/%s-output.class", set.generated.dot))); return new MergedClassResult(outputClass, re.getInnerClasses()); } catch (Error | RuntimeException e) { logger.error("Failure while merging classes.", e); AsmUtil.logClass(logger, "generatedClass", generatedClass); throw e; } }
public void remap(ClassNode cnode, ClassVisitor cv) { cstMappper.transform(cnode); cnode.accept(new RemappingClassAdapter(cv, obfMapper)); }
public ClassMangler(ClassVisitor visitor, String origName, String mangledName, String target) { super(Opcodes.ASM4, new RemappingClassAdapter(visitor, new SimpleRemapper(origName, mangledName))); this.mangledName = mangledName; this.target = target; }
@Override public ClassVisitor transform(ClassVisitor v) { return new RemappingClassAdapter(v, remapper); }
public static void process(File inFile, String outFile, final String version, final Logger logger) { Remapper remapper = new Remapper() { @Override public String map(String typeName) { for (String pre : repackaged) { if (typeName.startsWith(pre)) { Matcher matcher = versioned.matcher(typeName); if (matcher.matches()) { // Jar was compiled for older version, lets update the name pre = typeName.substring(0, matcher.start()); } String post = typeName.substring(pre.length(), typeName.length()); String newName = pre + version + "/" + post; // logger.info(typeName + " -> " + newName); return newName; } } return typeName; } }; try { logger.info("Reading " + inFile); JarInputStream inJar = new JarInputStream(new FileInputStream(inFile)); JarOutputStream out = new JarOutputStream(new FileOutputStream(outFile)); int processed = 0; JarEntry entry; while ((entry = inJar.getNextJarEntry()) != null) { if (entry.isDirectory()) { continue; } String name = entry.getName(); byte[] entryBytes = stream2Byte(inJar); // logger.info("Read " + name + " from input jar."); if (name.endsWith(".class")) { ClassReader cr = new ClassReader(entryBytes); ClassWriter cw = new ClassWriter(cr, 0); cr.accept(new RemappingClassAdapter(cw, remapper), ClassReader.EXPAND_FRAMES); entryBytes = cw.toByteArray(); // Unfortunately for us, Heroes implements an additonal version checker, so even though our bytecode is valid, it still won't run String heroes = "com/herocraftonline/heroes/util/VersionChecker.class"; if (name.equals(heroes)) { InputStream in = App.class.getClassLoader().getResourceAsStream(name); entryBytes = stream2Byte(in); in.close(); } processed++; // logger.info("Processed class file " + name); } out.putNextEntry(new JarEntry(name)); out.write(entryBytes); // logger.info("Added " + name + " to output jar."); } inJar.close(); out.close(); logger.info("Done! Processed " + processed + " files. The new jar is at " + outFile + ". Remember this jar is may not work correctly at all and could cause harm to your server. Test first!\n"); } catch (Exception ex) { logger.severe("Exception, check console for details!"); ex.printStackTrace(); } }