Commit 217737b3 authored by Skylot's avatar Skylot

core: add jadx visitors annotation for describe dependencies

parent efd8bd13
......@@ -22,6 +22,11 @@ import jadx.core.utils.exceptions.JadxException;
import java.util.List;
@JadxVisitor(
name = "ClassModifier",
desc = "Remove synthetic classes, methods and fields",
runAfter = ModVisitor.class
)
public class ClassModifier extends AbstractVisitor {
@Override
......@@ -129,6 +134,7 @@ public class ClassModifier extends AbstractVisitor {
if (af.isBridge() && af.isSynthetic() && !isMethodUniq(cls, mth)) {
// TODO add more checks before method deletion
mth.add(AFlag.DONT_GENERATE);
continue;
}
// remove synthetic constructor for inner non-static classes
if (af.isSynthetic() && af.isConstructor() && mth.getBasicBlocks().size() == 2) {
......
package jadx.core.dex.visitors;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation for describe dependencies of jadx visitors
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface JadxVisitor {
/**
* Visitor short name (identifier)
*/
String name();
/**
* Detailed visitor description
*/
String desc() default "";
/**
* This visitor must be run <b>after</b> listed visitors
*/
Class<? extends IDexTreeVisitor>[] runAfter() default {};
/**
* This visitor must be run <b>before</b> listed visitors
*/
Class<? extends IDexTreeVisitor>[] runBefore() default {};
}
......@@ -29,7 +29,13 @@ import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@JadxVisitor(
name = "ReSugarCode",
desc = "Simplify synthetic or verbose code",
runAfter = CodeShrinker.class
)
public class ReSugarCode extends AbstractVisitor {
private static final Logger LOG = LoggerFactory.getLogger(ReSugarCode.class);
@Override
......
......@@ -12,6 +12,8 @@ import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.visitors.AbstractVisitor;
import jadx.core.dex.visitors.JadxVisitor;
import jadx.core.dex.visitors.blocksmaker.BlockFinish;
import jadx.core.utils.InsnList;
import jadx.core.utils.InstructionRemover;
import jadx.core.utils.exceptions.JadxException;
......@@ -25,6 +27,11 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@JadxVisitor(
name = "SSATransform",
desc = "Calculate Single Side Assign (SSA) variables",
runAfter = BlockFinish.class
)
public class SSATransform extends AbstractVisitor {
@Override
......
package jadx.tests.functional;
import jadx.api.DefaultJadxArgs;
import jadx.core.Jadx;
import jadx.core.dex.visitors.IDexTreeVisitor;
import jadx.core.dex.visitors.JadxVisitor;
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.hamcrest.Matchers.empty;
import static org.junit.Assert.assertThat;
public class JadxVisitorsOrderTest {
private static final Logger LOG = LoggerFactory.getLogger(JadxVisitorsOrderTest.class);
@Test
public void testOrder() {
List<IDexTreeVisitor> passes = Jadx.getPassesList(new DefaultJadxArgs(), new File("out"));
List<String> errors = check(passes);
for (String str : errors) {
LOG.error(str);
}
assertThat(errors, empty());
}
private static List<String> check(List<IDexTreeVisitor> passes) {
List<Class> classList = new ArrayList<Class>(passes.size());
for (IDexTreeVisitor pass : passes) {
classList.add(pass.getClass());
}
List<String> errors = new ArrayList<String>();
Set<String> names = new HashSet<String>();
for (int i = 0; i < passes.size(); i++) {
IDexTreeVisitor pass = passes.get(i);
JadxVisitor info = pass.getClass().getAnnotation(JadxVisitor.class);
if (info == null) {
LOG.warn("No JadxVisitor annotation for visitor: {}", pass.getClass().getName());
continue;
}
String passName = pass.getClass().getSimpleName();
if (!names.add(passName)) {
errors.add("Visitor name conflict: " + passName + ", class: " + pass.getClass().getName());
}
for (Class<? extends IDexTreeVisitor> cls : info.runBefore()) {
if (classList.indexOf(cls) < i) {
errors.add("Pass " + passName + " must be before " + cls.getSimpleName());
}
}
for (Class<? extends IDexTreeVisitor> cls : info.runAfter()) {
if (classList.indexOf(cls) > i) {
errors.add("Pass " + passName + " must be after " + cls.getSimpleName());
}
}
}
return errors;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment