core: add api for write tests using smali
This commit is contained in:
@@ -1,9 +1,12 @@
|
|||||||
ext.jadxClasspath = 'clsp-data/android-4.3.jar'
|
ext.jadxClasspath = 'clsp-data/android-4.3.jar'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
runtime files(jadxClasspath)
|
||||||
|
|
||||||
compile files('lib/dx-1.8.jar')
|
compile files('lib/dx-1.8.jar')
|
||||||
compile 'org.ow2.asm:asm:5.0.3'
|
compile 'org.ow2.asm:asm:5.0.3'
|
||||||
runtime files(jadxClasspath)
|
|
||||||
|
testCompile 'org.smali:smali:2.0.3'
|
||||||
}
|
}
|
||||||
|
|
||||||
task packTests(type: Jar) {
|
task packTests(type: Jar) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import jadx.core.dex.nodes.ClassNode;
|
|||||||
import jadx.core.dex.nodes.MethodNode;
|
import jadx.core.dex.nodes.MethodNode;
|
||||||
import jadx.core.dex.visitors.DepthTraversal;
|
import jadx.core.dex.visitors.DepthTraversal;
|
||||||
import jadx.core.dex.visitors.IDexTreeVisitor;
|
import jadx.core.dex.visitors.IDexTreeVisitor;
|
||||||
|
import jadx.core.utils.exceptions.JadxException;
|
||||||
import jadx.core.utils.files.FileUtils;
|
import jadx.core.utils.files.FileUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -30,21 +31,30 @@ public abstract class InternalJadxTest extends TestUtils {
|
|||||||
|
|
||||||
protected boolean outputCFG = false;
|
protected boolean outputCFG = false;
|
||||||
protected boolean isFallback = false;
|
protected boolean isFallback = false;
|
||||||
protected boolean deleteTmpJar = true;
|
protected boolean deleteTmpFiles = true;
|
||||||
|
|
||||||
protected String outDir = "test-out-tmp";
|
protected String outDir = "test-out-tmp";
|
||||||
|
|
||||||
public ClassNode getClassNode(Class<?> clazz) {
|
public ClassNode getClassNode(Class<?> clazz) {
|
||||||
JadxDecompiler d = new JadxDecompiler();
|
|
||||||
try {
|
try {
|
||||||
d.loadFile(getJarForClass(clazz));
|
File jar = getJarForClass(clazz);
|
||||||
|
return getClassNodeFromFile(jar, clazz.getName());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail(e.getMessage());
|
fail(e.getMessage());
|
||||||
}
|
}
|
||||||
String clsName = clazz.getName();
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassNode getClassNodeFromFile(File file, String clsName) {
|
||||||
|
JadxDecompiler d = new JadxDecompiler();
|
||||||
|
try {
|
||||||
|
d.loadFile(file);
|
||||||
|
} catch (JadxException e) {
|
||||||
|
fail(e.getMessage());
|
||||||
|
}
|
||||||
ClassNode cls = d.getRoot().searchClassByName(clsName);
|
ClassNode cls = d.getRoot().searchClassByName(clsName);
|
||||||
assertNotNull("Class not found: " + clsName, cls);
|
assertNotNull("Class not found: " + clsName, cls);
|
||||||
assertEquals(cls.getFullName(), clazz.getName());
|
assertEquals(cls.getFullName(), clsName);
|
||||||
|
|
||||||
cls.load();
|
cls.load();
|
||||||
for (IDexTreeVisitor visitor : getPasses()) {
|
for (IDexTreeVisitor visitor : getPasses()) {
|
||||||
@@ -99,16 +109,26 @@ public abstract class InternalJadxTest extends TestUtils {
|
|||||||
String path = cls.getPackage().getName().replace('.', '/');
|
String path = cls.getPackage().getName().replace('.', '/');
|
||||||
List<File> list = getClassFilesWithInners(cls);
|
List<File> list = getClassFilesWithInners(cls);
|
||||||
|
|
||||||
File temp = File.createTempFile("jadx-tmp-", System.nanoTime() + ".jar");
|
File temp = createTempFile(".jar");
|
||||||
JarOutputStream jo = new JarOutputStream(new FileOutputStream(temp));
|
JarOutputStream jo = new JarOutputStream(new FileOutputStream(temp));
|
||||||
for (File file : list) {
|
for (File file : list) {
|
||||||
FileUtils.addFileToJar(jo, file, path + "/" + file.getName());
|
FileUtils.addFileToJar(jo, file, path + "/" + file.getName());
|
||||||
}
|
}
|
||||||
jo.close();
|
jo.close();
|
||||||
if (deleteTmpJar) {
|
return temp;
|
||||||
temp.deleteOnExit();
|
}
|
||||||
} else {
|
|
||||||
System.out.println("Temporary jar file path: " + temp.getAbsolutePath());
|
protected File createTempFile(String suffix) {
|
||||||
|
File temp = null;
|
||||||
|
try {
|
||||||
|
temp = File.createTempFile("jadx-tmp-", System.nanoTime() + suffix);
|
||||||
|
if (deleteTmpFiles) {
|
||||||
|
temp.deleteOnExit();
|
||||||
|
} else {
|
||||||
|
System.out.println("Temporary file path: " + temp.getAbsolutePath());
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail(e.getMessage());
|
||||||
}
|
}
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
@@ -135,7 +155,6 @@ public abstract class InternalJadxTest extends TestUtils {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Use only for debug purpose
|
// Use only for debug purpose
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected void setOutputCFG() {
|
protected void setOutputCFG() {
|
||||||
@@ -151,6 +170,6 @@ public abstract class InternalJadxTest extends TestUtils {
|
|||||||
// Use only for debug purpose
|
// Use only for debug purpose
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected void notDeleteTmpJar() {
|
protected void notDeleteTmpJar() {
|
||||||
this.deleteTmpJar = false;
|
this.deleteTmpFiles = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package jadx.api;
|
||||||
|
|
||||||
|
import jadx.core.Consts;
|
||||||
|
import jadx.core.dex.nodes.ClassNode;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jf.smali.main;
|
||||||
|
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
public class SmaliTest extends InternalJadxTest {
|
||||||
|
|
||||||
|
private static final String SMALI_TESTS_PROJECT = "jadx-core";
|
||||||
|
private static final String SMALI_TESTS_DIR = "src/test/smali";
|
||||||
|
private static final String SMALI_TESTS_EXT = ".smali";
|
||||||
|
|
||||||
|
protected ClassNode getClassNodeFromSmali(String clsName) {
|
||||||
|
File smaliFile = getSmaliFile(clsName);
|
||||||
|
File outDex = createTempFile(".dex");
|
||||||
|
compileSmali(smaliFile, outDex);
|
||||||
|
String fullClsName = Consts.DEFAULT_PACKAGE_NAME + "." + clsName;
|
||||||
|
return getClassNodeFromFile(outDex, fullClsName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getSmaliFile(String clsName) {
|
||||||
|
File smaliFile = new File(SMALI_TESTS_DIR, clsName + SMALI_TESTS_EXT);
|
||||||
|
if (smaliFile.exists()) {
|
||||||
|
return smaliFile;
|
||||||
|
}
|
||||||
|
smaliFile = new File(SMALI_TESTS_PROJECT, smaliFile.getPath());
|
||||||
|
if (smaliFile.exists()) {
|
||||||
|
return smaliFile;
|
||||||
|
}
|
||||||
|
fail("Smali file not found: " + SMALI_TESTS_DIR + "/" + clsName + SMALI_TESTS_EXT);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean compileSmali(File input, File output) {
|
||||||
|
List<String> args = new ArrayList<String>();
|
||||||
|
args.add(input.getAbsolutePath());
|
||||||
|
|
||||||
|
args.add("-o");
|
||||||
|
args.add(output.getAbsolutePath());
|
||||||
|
|
||||||
|
main.main(args.toArray(new String[args.size()]));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user