Skip to content

Commit

Permalink
Commit byte-buddy failure before removing
Browse files Browse the repository at this point in the history
  • Loading branch information
CalebFenton committed Feb 5, 2016
1 parent 624775b commit 67b8bad
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 11 deletions.
4 changes: 2 additions & 2 deletions smalivm/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ dependencies {
compile 'org.smali:smali:2.1.1'
compile 'org.smali:baksmali:2.1.1'

//compile 'net.bytebuddy:byte-buddy:0.8.0'
compile 'net.bytebuddy:byte-buddy:1.1.0'

// Contains Android framework classes that should be reflected instead of virtually executed
compile files('libs/android-local.jar')

// Manually patched to allow for multiple fields of the same name but different types
compile files('libs/byte-buddy-0.8-SNAPSHOT.jar')
// compile files('libs/byte-buddy-0.8-SNAPSHOT.jar')

// Testing
testCompile depends.junit
Expand Down
5 changes: 3 additions & 2 deletions smalivm/src/main/java/org/cf/smalivm/smali/ClassBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import net.bytebuddy.dynamic.DynamicType.Unloaded;
import net.bytebuddy.dynamic.TargetType;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.dynamic.scaffold.TypeValidation;
import net.bytebuddy.implementation.StubMethod;
import net.bytebuddy.jar.asm.Opcodes;

Expand Down Expand Up @@ -92,7 +93,7 @@ private void buildClass(String className, ClassDef classDef) throws ClassNotFoun

startBuilding(className);

ByteBuddy buddy = new ByteBuddy();
ByteBuddy buddy = new ByteBuddy().with(TypeValidation.DISABLED);
Builder<?> builder = setSuperclass(buddy, classDef.getSuperclass());
builder = setInterfaces(builder, classDef.getInterfaces());
builder = setAnnotations(builder, classDef.getAnnotations());
Expand Down Expand Up @@ -135,7 +136,7 @@ private void buildQueued() throws ClassNotFoundException {
private void buildShallowClass(String className, boolean isInterface) throws ClassNotFoundException {
startBuilding(className);

ByteBuddy buddy = new ByteBuddy();
ByteBuddy buddy = new ByteBuddy().with(TypeValidation.DISABLED);
Builder<?> builder = setSuperclass(buddy, "Ljava/lang/Object;");
builder = builder.name(className);
ModifierContributor.ForType[] modifiers = getShallowTypeModifiers(isInterface);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.cf.smalivm.smali;

import java.util.HashSet;
import java.util.Set;

import org.jf.dexlib2.iface.ClassDef;
import org.jf.dexlib2.iface.Field;
import org.jf.dexlib2.iface.Method;

public class ClassDependencyCollector {

public static Set<String> collect(ClassDef classDef) {
Set<String> dependencies = new HashSet<String>();

dependencies.add(classDef.getType());
dependencies.add(classDef.getSuperclass());
dependencies.addAll(classDef.getInterfaces());
dependencies.addAll(collectMethodDependencies(classDef.getMethods()));
dependencies.addAll(collectFieldDependencies(classDef.getFields()));

return dependencies;
}

private static Set<String> collectMethodDependencies(Iterable<? extends Method> methods) {
Set<String> dependencies = new HashSet<String>();
for (Method method : methods) {
for (CharSequence parameterType : method.getParameterTypes()) {
dependencies.add(parameterType.toString());
}
}

return dependencies;
}

private static Set<String> collectFieldDependencies(Iterable<? extends Field> fields) {
Set<String> dependencies = new HashSet<String>();
for (Field field : fields) {
dependencies.add(field.getType());
}

return dependencies;
}

}
37 changes: 30 additions & 7 deletions smalivm/src/main/java/org/cf/smalivm/smali/SmaliClassLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.annotation.Nullable;

import org.cf.util.ClassNameUtils;
import org.jf.dexlib2.iface.ClassDef;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -69,20 +72,40 @@ protected Class<?> findClass(String name) {
return cachedClasses.get(name);
}

private void filterAvailableClasses(Set<String> classNames) {
Iterator<String> iter = classNames.iterator();
while (iter.hasNext()) {
String className = iter.next();
String baseName = ClassNameUtils.getComponentBase(className);
String binaryName = ClassNameUtils.internalToBinary(baseName);
if (loadClassWithoutBuilding(binaryName) != null) {
iter.remove();
}
}
}

@Override
public synchronized Class<?> loadClass(String name) throws ClassNotFoundException {
Class<?> klazz = loadClassWithoutBuilding(name);
if (klazz != null) {
return klazz;
}

if (cachedClasses.isEmpty()) {
Set<String> classNames = classManager.getNonFrameworkClassNames();
// If I don't set this to null first, cachedClasses does not update.
// VERY VERY STRANGE
cachedClasses = null;
cachedClasses = classBuilder.build(classNames);
}
ClassDef classDef = classManager.getClass(ClassNameUtils.binaryToInternal(name));
Set<String> classNames = ClassDependencyCollector.collect(classDef);
filterAvailableClasses(classNames);
Map<String, Class<?>> newClasses = classBuilder.build(classNames);
cachedClasses.putAll(newClasses);

// if (cachedClasses.isEmpty()) {
// Set<String> classNames = classManager.getNonFrameworkClassNames();
// classNames.clear();
// classNames.add(name);
// If I don't set this to null first, cachedClasses does not update.
// VERY VERY STRANGE
// cachedClasses = null;
// cachedClasses = classBuilder.build(classNames);
// }

klazz = findClass(name);
if (klazz == null) {
Expand Down
11 changes: 11 additions & 0 deletions smalivm/src/test/java/org/cf/smalivm/smali/ClassBuilderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,17 @@ public void canBuildInterfaceDoubleDependency() throws Exception {
Class<?> klazz = classes.get(className);
}

@Test
public void testy() throws ClassNotFoundException, IOException {
classManager = new ClassManagerFactory().build("../simplify/obfuscated-example");
classBuilder = new ClassBuilder(classManager);
String className = "android.support.v4.media.TransportMediatorJellybeanMR2$2";
className = "org.cf.obfuscated.Reflection";
// android.support.v4.view.accessibility.AccessibilityNodeInfoCompatJellybeanMr2
Map<String, Class<?>> classes = classBuilder.build(className);

}

@Test
public void canBuildSelfReferencingClass() throws Exception {
String className = "org.cf.test.SelfReference";
Expand Down

0 comments on commit 67b8bad

Please sign in to comment.