use of org.objectweb.asm.ClassWriter in project Valkyrien-Warfare-Revamped by ValkyrienWarfare.
the class ValkyrienWarfareTransformer method transform.
@Override
public byte[] transform(String name, String transformedName, byte[] classData) {
classData = transformer.transform(classData);
TransformAdapter adapter = new TransformAdapter(ASM5, ValkyrienWarfarePlugin.isObfuscatedEnvironment, transformedName);
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
adapter.setCV(classWriter);
try {
new ClassReader(classData).accept(adapter, ClassReader.EXPAND_FRAMES);
classData = classWriter.toByteArray();
//Performs sanity checks and frame stack recalculations before pushing the new bytecode
// ClassReader cr = new ClassReader(byteArray);
// ClassWriter checkedWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
// CheckClassAdapter adapterChecker = new CheckClassAdapter(checkedWriter, true);
// cr.accept(adapterChecker, ClassReader.EXPAND_FRAMES);
// return checkedWriter.toByteArray();
} catch (Exception e) {
// System.out.println(transformedName);
e.printStackTrace();
}
return classData;
}
use of org.objectweb.asm.ClassWriter in project android_frameworks_base by ResurrectionRemix.
the class DelegateClassAdapterTest method testConstructorsNotSupported.
/**
* {@link DelegateMethodAdapter} does not support overriding constructors yet,
* so this should fail with an {@link UnsupportedOperationException}.
*
* Although not tested here, the message of the exception should contain the
* constructor signature.
*/
@Test(expected = UnsupportedOperationException.class)
public void testConstructorsNotSupported() throws IOException {
ClassWriter cw = new ClassWriter(0);
String internalClassName = NATIVE_CLASS_NAME.replace('.', '/');
HashSet<String> delegateMethods = new HashSet<>();
delegateMethods.add("<init>");
DelegateClassAdapter cv = new DelegateClassAdapter(mLog, cw, internalClassName, delegateMethods);
ClassReader cr = new ClassReader(NATIVE_CLASS_NAME);
cr.accept(cv, 0);
}
use of org.objectweb.asm.ClassWriter in project android_frameworks_base by ResurrectionRemix.
the class DelegateClassAdapterTest method testDelegateInner.
@Test
public void testDelegateInner() throws Throwable {
// We'll delegate the "get" method of both the inner and outer class.
HashSet<String> delegateMethods = new HashSet<>();
delegateMethods.add("get");
delegateMethods.add("privateMethod");
// Generate the delegate for the outer class.
ClassWriter cwOuter = new ClassWriter(0);
String outerClassName = OUTER_CLASS_NAME.replace('.', '/');
DelegateClassAdapter cvOuter = new DelegateClassAdapter(mLog, cwOuter, outerClassName, delegateMethods);
ClassReader cr = new ClassReader(OUTER_CLASS_NAME);
cr.accept(cvOuter, 0);
// Generate the delegate for the inner class.
ClassWriter cwInner = new ClassWriter(0);
String innerClassName = INNER_CLASS_NAME.replace('.', '/');
DelegateClassAdapter cvInner = new DelegateClassAdapter(mLog, cwInner, innerClassName, delegateMethods);
cr = new ClassReader(INNER_CLASS_NAME);
cr.accept(cvInner, 0);
// Load the generated classes in a different class loader and try them
ClassLoader2 cl2 = null;
try {
cl2 = new ClassLoader2() {
@Override
public void testModifiedInstance() throws Exception {
// Check the outer class
Class<?> outerClazz2 = loadClass(OUTER_CLASS_NAME);
Object o2 = outerClazz2.newInstance();
assertNotNull(o2);
// The original Outer.get returns 1+10+20,
// but the delegate makes it return 4+10+20
assertEquals(4 + 10 + 20, callGet(o2, 10, 20));
assertEquals(1 + 10 + 20, callGet_Original(o2, 10, 20));
// The original Outer has a private method,
// so by default we can't access it.
boolean gotIllegalAccessException = false;
try {
callMethod(o2, "privateMethod", false);
} catch (IllegalAccessException e) {
gotIllegalAccessException = true;
}
assertTrue(gotIllegalAccessException);
// The private method from original Outer has been
// delegated. The delegate generated should have the
// same access.
gotIllegalAccessException = false;
try {
assertEquals("outerPrivateMethod", callMethod(o2, "privateMethod_Original", false));
} catch (IllegalAccessException e) {
gotIllegalAccessException = true;
}
assertTrue(gotIllegalAccessException);
// Check the inner class. Since it's not a static inner class, we need
// to use the hidden constructor that takes the outer class as first parameter.
Class<?> innerClazz2 = loadClass(INNER_CLASS_NAME);
Constructor<?> innerCons = innerClazz2.getConstructor(outerClazz2);
Object i2 = innerCons.newInstance(o2);
assertNotNull(i2);
// The original Inner.get returns 3+10+20,
// but the delegate makes it return 6+10+20
assertEquals(6 + 10 + 20, callGet(i2, 10, 20));
assertEquals(3 + 10 + 20, callGet_Original(i2, 10, 20));
}
};
cl2.add(OUTER_CLASS_NAME, cwOuter.toByteArray());
cl2.add(INNER_CLASS_NAME, cwInner.toByteArray());
cl2.testModifiedInstance();
} catch (Throwable t) {
throw dumpGeneratedClass(t, cl2);
}
}
use of org.objectweb.asm.ClassWriter in project android_frameworks_base by ResurrectionRemix.
the class StubMethodAdapterTest method testBoolean.
/**
* @param methodPredicate tests if the method should be replaced
*/
private void testBoolean(BiPredicate<String, Type> methodPredicate, Consumer<Boolean> assertion, String methodName) throws Exception {
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
// Always rename the class to avoid conflict with the original class.
String newClassName = STUB_CLASS_NAME + '_';
new ClassReader(STUB_CLASS_NAME).accept(new ClassAdapter(newClassName, writer, methodPredicate), 0);
MyClassLoader myClassLoader = new MyClassLoader(newClassName, writer.toByteArray());
Class<?> aClass = myClassLoader.loadClass(newClassName);
assertTrue("StubClass not loaded by the classloader. Likely a bug in the test.", myClassLoader.findClassCalled);
Method method = aClass.getMethod(methodName);
Object o = aClass.newInstance();
assertion.accept((Boolean) method.invoke(o));
}
use of org.objectweb.asm.ClassWriter in project android_frameworks_base by ResurrectionRemix.
the class AsmGenerator method transform.
/**
* Transforms a class.
* <p/>
* There are 3 kind of transformations:
*
* 1- For "mock" dependencies classes, we want to remove all code from methods and replace
* by a stub. Native methods must be implemented with this stub too. Abstract methods are
* left intact. Modified classes must be overridable (non-private, non-final).
* Native methods must be made non-final, non-private.
*
* 2- For "keep" classes, we want to rewrite all native methods as indicated above.
* If a class has native methods, it must also be made non-private, non-final.
*
* Note that unfortunately static methods cannot be changed to non-static (since static and
* non-static are invoked differently.)
*/
byte[] transform(ClassReader cr, boolean stubNativesOnly) {
boolean hasNativeMethods = hasNativeMethods(cr);
// Get the class name, as an internal name (e.g. com/android/SomeClass$InnerClass)
String className = cr.getClassName();
String newName = transformName(className);
// transformName returns its input argument if there's no need to rename the class
if (!newName.equals(className)) {
mRenameCount++;
// This class is being renamed, so remove it from the list of classes not renamed.
mClassesNotRenamed.remove(className);
}
mLog.debug("Transform %s%s%s%s", className, newName.equals(className) ? "" : " (renamed to " + newName + ")", hasNativeMethods ? " -- has natives" : "", stubNativesOnly ? " -- stub natives only" : "");
// Rewrite the new class from scratch, without reusing the constant pool from the
// original class reader.
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassVisitor cv = cw;
// FIXME Generify
if ("android/content/res/Resources".equals(className)) {
cv = new FieldInjectorAdapter(cv);
}
if (mReplaceMethodCallsClasses.contains(className)) {
cv = new ReplaceMethodCallsAdapter(cv, className);
}
cv = new RefactorClassAdapter(cv, mRefactorClasses);
if (!newName.equals(className)) {
cv = new RenameClassAdapter(cv, className, newName);
}
String binaryNewName = newName.replace('/', '.');
if (mInjectedMethodsMap.keySet().contains(binaryNewName)) {
cv = new InjectMethodsAdapter(cv, mInjectedMethodsMap.get(binaryNewName));
}
cv = new TransformClassAdapter(mLog, mStubMethods, mDeleteReturns.get(className), newName, cv, stubNativesOnly);
Set<String> delegateMethods = mDelegateMethods.get(className);
if (delegateMethods != null && !delegateMethods.isEmpty()) {
// known to have no native methods, just skip this step.
if (hasNativeMethods || !(delegateMethods.size() == 1 && delegateMethods.contains(DelegateClassAdapter.ALL_NATIVES))) {
cv = new DelegateClassAdapter(mLog, cv, className, delegateMethods);
}
}
Set<String> promoteFields = mPromotedFields.get(className);
if (promoteFields != null && !promoteFields.isEmpty()) {
cv = new PromoteFieldClassAdapter(cv, promoteFields);
}
cr.accept(cv, 0);
return cw.toByteArray();
}
Aggregations