private byte[] classNodeToBytes(ClassNode classNode) { ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); classNode.accept(writer); byte[] bytes = writer.toByteArray(); // verify bytecode if (verifyAndPrint) { ClassReader reader = new ClassReader(bytes); ClassVisitor tracer = new TraceClassVisitor(new PrintWriter(System.out)); ClassVisitor checker = new CheckClassAdapter(tracer, true); reader.accept(checker, 0); } return bytes; }
/** * Verify class bytecode * * @param classBytes Class data * @return Class data, if it was valid * @throws ClassFormatError If class wasn't valid */ @Contract("null -> fail") public static byte[] checkGeneratedClass(byte[] classBytes) throws ClassFormatError { Ensure.notNull(classBytes, "Class data shouldn't be null!"); ClassReader cr = new ClassReader(classBytes); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); try { CheckClassAdapter.verify(cr, false, pw); } catch (Exception ignored) {} if(sw.toString().length() > 0) { throw new ClassFormatError(sw.toString()); } return classBytes; }
/** * See {@link org.objectweb.asm.util.CheckClassAdapter#CheckClassAdapter(ClassVisitor, boolean)}. * @param api the api version */ protected DrillCheckClassAdapter(final int api, final ClassVisitor cv, final boolean checkDataFlow) { super(api); /* * We set up a chain of class visitors: * this -> InnerAccessStripper -> CheckClassAdapter -> AccessRestorer -> cv * Note the AccessRestorer references accessStripper to get the original * access bits; the inner class could not be constructed before the call to * super(), hence the need to set the delegate after that. */ accessStripper = new InnerClassAccessStripper(api, new CheckClassAdapter( new AccessRestorer(api, cv), checkDataFlow)); setDelegate(accessStripper); }
@Override public void write(File file) throws IOException { JarOutputStream jos = new JarOutputStream(new FileOutputStream(file)); try { for (Iterator<ClassNode> itr = iterator(); itr.hasNext(); ) { ClassNode node = itr.next(); ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); node.accept(new CheckClassAdapter(writer, true)); byte[] bytes = writer.toByteArray(); jos.putNextEntry(new JarEntry(node.name.concat(".class"))); jos.write(bytes); } } finally { jos.close(); } }
private static void publicize(Path inPath, Path outPath) throws IOException { try (JarInputStream in = new JarInputStream(Files.newInputStream(inPath))) { try (JarOutputStream out = new JarOutputStream(Files.newOutputStream(outPath))) { JarEntry entry; while ((entry = in.getNextJarEntry()) != null) { if (entry.isDirectory()) { continue; } String name = entry.getName(); out.putNextEntry(new JarEntry(name)); if (name.endsWith(".class")) { ClassWriter writer = new ClassWriter(0); ClassReader reader = new ClassReader(in); reader.accept(new CheckClassAdapter(new ClassDefinalizer(new ClassPublicizer(writer)), true), 0); out.write(writer.toByteArray()); } else { ByteStreams.copy(in, out); } } } } }
/** * Validate a generated class * * @param reader The class to read * @param loader The appropriate class loader * @throws RuntimeException On bad validation */ public static void validateClass(ClassReader reader, ClassLoader loader) { StringWriter writer = new StringWriter(); PrintWriter printWriter = new PrintWriter(writer); Exception error = null; try { CheckClassAdapter.verify(reader, loader, false, printWriter); } catch (Exception e) { error = e; } String contents = writer.toString(); if (error != null || contents.length() > 0) { throw new IllegalStateException(writer.toString(), error); } }
private void instrumentClass(String className, Function<ClassVisitor, ClassVisitor> createShuffler, ZipFile rt, ZipOutputStream outZip) throws IOException { InputStream classStream = null; try { classStream = rt.getInputStream(rt.getEntry(className)); } catch (IOException exc) { Logger.getGlobal().log(Level.WARNING, "Cannot find " + className + " are you sure this is a valid rt.jar?"); Logger.getGlobal().log(Level.WARNING, "Continuing without instrumenting: " + className); } ClassReader cr = new ClassReader(classStream); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); ClassVisitor cv = createShuffler.apply(cw); cr.accept(cv, 0); byte[] arr = cw.toByteArray(); cr = new ClassReader(arr); cr.accept(new CheckClassAdapter(new ClassWriter(0)), 0); ZipEntry zipEntry = new ZipEntry(className); outZip.putNextEntry(zipEntry); outZip.write(arr, 0, arr.length); outZip.closeEntry(); }
public static MethodHandle createFunction(Supplier<byte[]> generator, MethodType methodType) { byte[] array = generator.get(); ClassReader reader = new ClassReader(array); CheckClassAdapter.verify(reader, true, new PrintWriter(System.out)); Class<?> type = new ClassLoader() { Class<?> createClass() { return defineClass("Foo", array, 0, array.length); } }.createClass(); try { return MethodHandles.publicLookup().findStatic(type, "foo", methodType); } catch (NoSuchMethodException | IllegalAccessException e) { throw new AssertionError(e); } }
public void validateClass(ClassReader reader) { StringWriter writer = new StringWriter(); PrintWriter printWriter = new PrintWriter(writer); Exception error = null; try { CheckClassAdapter.verify(reader, this, false, printWriter); } catch (Exception e) { error = e; } String contents = writer.toString(); if (error != null || contents.length() > 0) { reader.accept(new TraceClassVisitor(printWriter), 0); throw new RuntimeException("Generation error\nDump for " + reader.getClassName() + "\n" + writer.toString(), error); } }
@Override public Class<?> loadClass(String fullyQualifiedTargetClass) throws ClassNotFoundException { if (!testClass.equals(fullyQualifiedTargetClass)) { return super.loadClass(fullyQualifiedTargetClass); } String className = fullyQualifiedTargetClass.replace('.', '/'); InputStream is = java.lang.ClassLoader.getSystemResourceAsStream(className + ".class"); if (is == null) { throw new ClassNotFoundException("Class " + fullyQualifiedTargetClass + "could not be found!"); } ClassReader reader = null; try { reader = new ClassReader(is); } catch (IOException exc) { throw new ClassNotFoundException(); } ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS); ClassVisitor cv = new TestValuesDeterminerClassVisitor(fullyQualifiedTargetClass, writer); CheckClassAdapter checkClassAdapter = new CheckClassAdapter(cv); reader.accept(checkClassAdapter, ClassReader.SKIP_FRAMES); byte[] byteBuffer = writer.toByteArray(); Class<?> result = defineClass(fullyQualifiedTargetClass, byteBuffer, 0, byteBuffer.length); return result; }
/** * Validate a generated class * * @param reader The class to read * @param loader The appropriate class loader * @throws RuntimeException On bad validation */ public static void validateClass(ClassReader reader, ClassLoader loader) { StringWriter writer = new StringWriter(); PrintWriter printWriter = new PrintWriter(writer); Exception error = null; try { CheckClassAdapter.verify(reader, loader, false, printWriter); } catch (Exception e) { error = e; } String contents = writer.toString(); if (error != null || contents.length() > 0) { throw new ValidationException(reader, writer.toString(), error); } }
@Override public byte[] transform(String s, String s2, byte[] bytes) { if (bytes == null) { return bytes; } try { ClassReader cr = new ClassReader(bytes); ClassNode classNode = new ClassNode(); cr.accept(classNode, ClassReader.EXPAND_FRAMES); if (transform(s, s2, classNode)) { ClassWriter cw = new ClassWriter(cr, COMPUTE_MAXS); classNode.accept(new CheckClassAdapter(cw)); bytes = cw.toByteArray(); } } catch (Throwable t) { t.printStackTrace(); } return bytes; }
private SoyClassWriter(Writer writer, Builder builder) { super(writer.api(), Flags.DEBUG ? new CheckClassAdapter(writer, false) : writer); this.writer = writer; this.typeInfo = builder.type; super.visit( Opcodes.V1_7, builder.access, builder.type.internalName(), null /* not generic */, builder.baseClass.internalName(), builder.interfaces.toArray(new String[builder.interfaces.size()])); if (builder.fileName != null) { super.visitSource( builder.fileName, // No JSR-45 style source maps, instead we write the line numbers in the normal locations. null); } }
public static byte[] dump() throws Exception { ClassWriter cw = new ClassWriter(0); ClassVisitor cv = new CheckClassAdapter(cw); cv.visit(52, ACC_PUBLIC + ACC_SUPER, "json/BeanJsonifier2", "Ljava/lang/Object;Ljson/Jsonifier<Ljson/Bean;>;", "java/lang/Object", new String[] { "json/Jsonifier" }); cv.visitSource("BeanJsonifier2.java", null); generateConstructor(cv); generateMarshal(cv); generateBridge(cv); cv.visitEnd(); return cw.toByteArray(); }
public byte[] generateBytecode() { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); ClassVisitor cv = new CheckClassAdapter(cw, true); cv.visit( 52, ACC_PUBLIC, jsonifierClassPath, "Ljava/lang/Object;Ljson/Jsonifier<L" + jsonPath+ ";>;", BASE_CLASS_INTERNAL_NAME, new String[] { "json/Jsonifier" }); cv.visitSource(getClass().getName().replace('.', '/') + ".java", null); generateConstructor(cv); generateMarshal(cv); generateMarshalBridge(cv); cv.visitEnd(); return cw.toByteArray(); }
public String dumpVerify(byte[] bytecode, ClassLoader classLoader) { if (bytecode == null) { throw new NullPointerException("bytecode must not be null"); } if (classLoader == null) { throw new NullPointerException("classLoader must not be null"); } final StringWriter out = new StringWriter(); final PrintWriter writer = new PrintWriter(out); final ClassReader cr = new ClassReader(bytecode); CheckClassAdapter.verify(cr, classLoader, true, writer); return out.toString(); }
/** * Weave tracking method call if the annotations present. */ private static void weaveIfNecessary(ClassReader classReader, File dest) throws IOException { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); ModifierClassWriter mcw = new ModifierClassWriter(Opcodes.ASM5, cw); classReader.accept(new CheckClassAdapter(mcw), ClassReader.EXPAND_FRAMES); if (!mcw.isProceed()) { return; } OutputStream out = null; try { out = new FileOutputStream(dest); out.write(cw.toByteArray()); out.flush(); } finally { closeQuietly(out); } }
@SuppressWarnings("unused") private static void printClass(final byte[] classfileBuffer, final String classname) { /* final TraceClassVisitor v = new TraceClassVisitor(new PrintWriter(System.out)); new ClassReader(classfileBuffer).accept(v, ClassReader.SKIP_DEBUG); */ final ClassNode cn = new ClassNode(); final ClassReader cr = new ClassReader(classfileBuffer); //cr.accept(new CheckClassAdapter(cn), ClassReader.SKIP_DEBUG); cr.accept(new CheckClassAdapter(cn), 0); for (final Object methodObj : cn.methods) { final MethodNode method = (MethodNode) methodObj; final Analyzer a = new Analyzer(new BasicVerifier()); //final Analyzer a = new Analyzer(new SimpleVerifier()); try { a.analyze(cn.name, method); } catch (final AnalyzerException e) { System.err.println("// error in method " + classname + "." + method.name + method.desc + ":" + e); } printMethod(a, System.err, method); } }
private void checkBytecode(ClassLoader loader, String className, byte[] bc, int wFlags) { ClassReader debugReader = new ClassReader(bc); ClassWriter debugWriter = new ContextClassWriter(loader, wFlags); try { ClassNode debugNode = new ClassNode(Opcodes.ASM5); debugReader.accept(debugNode, ClassReader.EXPAND_FRAMES); debugNode.accept(new CheckClassAdapter(debugWriter)); // debugReader.accept(new CheckClassAdapter(debugWriter), 0); } catch (RuntimeException ex) { System.err.println("Bytecode check failed for " + className + ":"); ex.printStackTrace(); System.exit(-1); } }
/** * See {@link org.objectweb.asm.util.CheckClassAdapter#verify(ClassReader, boolean, PrintWriter)}. */ public static void verify(final ClassReader cr, final boolean dump, final PrintWriter pw) { /* * For plain verification, we don't need to restore the original access * bytes the way we do when the check adapter is used as part of a chain, so * we can just strip it and use the ASM version directly. */ final ClassWriter classWriter = new ClassWriter(0); cr.accept(new InnerClassAccessStripper(CompilationConfig.ASM_API_VERSION, classWriter), ClassReader.SKIP_DEBUG); final ClassReader strippedCr = new ClassReader(classWriter.toByteArray()); CheckClassAdapter.verify(strippedCr, dump, pw); }
private void instrumentClass(MethodDatabase db, File f) { db.log(LogLevel.INFO, "Instrumenting class %s", f); try { ClassReader r; FileInputStream fis = new FileInputStream(f); try { r = new ClassReader(fis); } finally { fis.close(); } ClassWriter cw = new DBClassWriter(db, r); ClassVisitor cv = check ? new CheckClassAdapter(cw) : cw; InstrumentClass ic = new InstrumentClass(cv, db, false); r.accept(ic, ClassReader.SKIP_FRAMES); byte[] newClass = cw.toByteArray(); if(writeClasses) { FileOutputStream fos = new FileOutputStream(f); try { fos.write(newClass); } finally { fos.close(); } } } catch (IOException ex) { throw new BuildException("Instrumenting file " + f, ex); } }
static byte[] instrumentClass(MethodDatabase db, byte[] data, boolean check) { ClassReader r = new ClassReader(data); ClassWriter cw = new DBClassWriter(db, r); ClassVisitor cv = check ? new CheckClassAdapter(cw) : cw; InstrumentClass ic = new InstrumentClass(cv, db, false); r.accept(ic, ClassReader.SKIP_FRAMES); return cw.toByteArray(); }
private byte[] apply(final RClass cls) { ClassReader reader = new ClassReader(cls.data); ClassWriter writer = new ClassWriter(0); int flags = removeFrames ? ClassReader.SKIP_FRAMES : ClassReader.EXPAND_FRAMES; reader.accept(new ClassRemapper(check ? new CheckClassAdapter(writer) : writer, remapper), flags); // TODO: compute frames (-Xverify:all -XX:-FailOverToOldVerifier) return writer.toByteArray(); }
public void analyze(OutputStream out) { for (Map.Entry<String, byte[]> e : classBytes.entrySet()) { ClassReader reader = new ClassReader(e.getValue()); ClassVisitor visitor = new CheckClassAdapter(new TraceClassVisitor(new PrintWriter(out, true))); reader.accept(visitor, 0); } }
private static void validateDataFlow(String name, byte[] data) { try { ClassReader cr = new ClassReader(data); ClassWriter cw = new ClassWriter(cr, 0); ClassVisitor cv = new CheckClassAdapter(cw, true); cr.accept(cv, 0); } catch (Exception ex) { logger.warn("Class {} failed validation", name, ex); } }
public static void verifyClass(byte[] bytes) { StringWriter sw = new StringWriter(); PrintWriter printer = new PrintWriter(sw); CheckClassAdapter.verify(new ClassReader(bytes), false, printer); String result = sw.toString(); if (result.length() > 0) { throw new RuntimeException(result); } }
public Class<?> loadClass(ClassCompilationContext ctx) { // generate bytecode ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); ctx.getClazz().accept(cw); // load class Class<?> cls; byte[] bb = cw.toByteArray(); String className = Type.getObjectType(ctx.getClazz().name).getClassName(); // try { // Files.write(bb, new File("target/compiledRecipes/" + ctx.clazz.name // + ".class")); // } catch (IOException e2) { // throw new SaltaException("Error while writing generated class", e2); // } try { cls = getLoader().defineClass(className, bb); ctx.initFields(cls); } catch (Throwable e) { System.out.println("Error while loading compiled recipe class"); ClassReader cr = new ClassReader(bb); cr.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(System.out)), 0); CheckClassAdapter.verify(cr, false, new PrintWriter(System.err)); throw new SaltaException("Error while loading compiled recipe", e); } // return result return cls; }
/** * Compiles the program while checking the ASM visitor calls made by the compiler. * This method is for debug purposes only and should not be used in production. */ public void compileDebug() { // Set debug visitor this.visitor = new CheckClassAdapter(this.writer, false); // Call compile as normal this.compile(); }
private static byte[] generateClass(String internalClassName, Type testClassType, List<Actor> actors, List<Object> objArgs, boolean waitsEnabled) { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); CheckClassAdapter cca = new CheckClassAdapter(cw, false); cca.visit(52, ACC_PUBLIC + ACC_SUPER, internalClassName, null, TEST_THREAD_EXECUTION_TYPE.getInternalName(), null); generateConstructor(cca); generateRun(cca, testClassType, actors, objArgs, waitsEnabled); cca.visitEnd(); return cw.toByteArray(); }
private boolean verifyClassBytes(final byte[] bytes) { final StringWriter sw = new StringWriter(); final PrintWriter pw = new PrintWriter(sw); CheckClassAdapter.verify(new ClassReader(bytes), false, pw); final String result = sw.toString(); if (result.length() > 0) logger.error(result); return result.length() == 0; }
public final static void checkAsmBytes(byte[] bytes, PrintWriter pw) { try { ClassReader cr = new ClassReader(bytes); CheckClassAdapter.verify(cr, true, pw); } catch (Exception e) { e.printStackTrace(); } }
private static void implementInterface(ClassNode cn) throws Exception { // MethodNode fromMethod = new MethodNode(ACC_PUBLIC, "fromData", // "(Ljava/io/DataInput;)V", null, new String[] { // "java/io/IOException", // "java/lang/ClassNotFoundException" }); // mv = cw.visitMethod(ACC_PUBLIC, "toData", "(Ljava/io/DataOutput;)V", // null, new String[] { "java/io/IOException" }); MethodNode toMethod = new MethodNode(ACC_PUBLIC, "toData", "(Ljava/io/DataOutput;)V", null, new String[] { "java/io/IOException" }); InsnList instToMethod = toMethod.instructions; for (int i = 0; i < cn.fields.size(); i++) { FieldNode fn = (FieldNode) cn.fields.get(i); toMethod(cn.name, fn, instToMethod); } instToMethod.add(new InsnNode(RETURN)); cn.methods.add(toMethod); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); cn.accept(cw); byte[] bt = cw.toByteArray(); ClassReader cr = new ClassReader(bt); CheckClassAdapter ca = new CheckClassAdapter(cw); FileOutputStream fo = new FileOutputStream("d:/x1.log"); PrintWriter pw = new PrintWriter(fo); ca.verify(cr, true, pw); ByteArrayClassLoader bacl = new ByteArrayClassLoader(bt); Class cls = bacl.loadClass("ynd.test.Ac01"); DataSerializable di = (DataSerializable) cls.newInstance(); di.toData(null); }
private byte[] assertValidClass(final Class<?> clazz) throws IllegalClassFormatException { final byte[] bs = transform(clazz); // printClass(bs); final StringWriter sw = new StringWriter(); CheckClassAdapter.verify(new ClassReader(bs), false, new PrintWriter(sw)); assertTrue(sw.toString(), sw.toString().length() == 0); return bs; }
private static boolean verifyClass(String name, InputStream is, PrintWriter err, boolean verbose) throws IOException { ClassReader cr = new ClassReader(is); ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); ClassVisitor cv = new CheckClassAdapter(cw); cr.accept(cv, 0); return verify(name, new ClassReader(cw.toByteArray()), err, verbose); }
/** {@inheritDoc} */ @Override public Class<?> loadClass(String fullyQualifiedTargetClass) throws ClassNotFoundException { if (isSystemClass(fullyQualifiedTargetClass)) { logger.info("Not instrumenting class '{}'.", fullyQualifiedTargetClass); return super.loadClass(fullyQualifiedTargetClass); } logger.info("Instrumenting class '{}'.", fullyQualifiedTargetClass); String className = fullyQualifiedTargetClass.replace('.', '/'); InputStream is = java.lang.ClassLoader.getSystemResourceAsStream(className + ".class"); if (is == null) { throw new ClassNotFoundException("Class " + fullyQualifiedTargetClass + "could not be found!"); } ClassReader reader = null; try { reader = new ClassReader(is); } catch (IOException exc) { throw new ClassNotFoundException(); } ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS); ClassVisitor cv = new StatementTracingVisitor(fullyQualifiedTargetClass, writer); CheckClassAdapter checkClassAdapter = new CheckClassAdapter(cv); reader.accept(checkClassAdapter, ClassReader.SKIP_FRAMES); byte[] byteBuffer = writer.toByteArray(); Class<?> result = defineClass(fullyQualifiedTargetClass, byteBuffer, 0, byteBuffer.length); return result; }
private byte[] getInstrumentedBytes(String className, ClassNode classNode, boolean containsStubs) throws ClassNotFoundException { new ClassInstrumentor(classNode, containsStubs).instrument(); ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS) { @Override public int newNameType(String name, String desc) { return super.newNameType(name, desc.charAt(0) == ')' ? remapParams(desc) : remapParamType(desc)); } @Override public int newClass(String value) { value = remapType(value); return super.newClass(value); } }; classNode.accept(classWriter); byte[] classBytes = classWriter.toByteArray(); if (debug) { try { FileOutputStream fileOutputStream = new FileOutputStream("tmp/" + className + ".class"); fileOutputStream.write(classBytes); fileOutputStream.close(); CheckClassAdapter.verify(new ClassReader(classBytes), true, new PrintWriter(new FileWriter("tmp/" + className + ".analysis", false))); new ClassReader(classBytes).accept(new TraceClassVisitor(new PrintWriter(new FileWriter("tmp/" + className + ".dis", false))), 0); } catch (IOException e) { throw new RuntimeException(e); } } return classBytes; }