add cmd asm-verify jar2dex

--HG--
branch : 0.0.9.x
This commit is contained in:
Panxiaobo 2012-01-02 19:05:17 +08:00
parent 62898aa689
commit 329080cd95
11 changed files with 314 additions and 13 deletions

View File

@ -52,7 +52,7 @@ public class ASMifierFileV implements OdexFileVisitor {
}
public static void main(String... args) throws IOException {
if (args.length < 2) {
if (args.length < 1) {
System.out.println("ASMifier 1.dex 2.dex ... n.dex");
return;
}

View File

@ -2,4 +2,4 @@
set CLASSPATH=
FOR %%i IN ("%~dp0lib\*.jar") DO CALL "%~dp0setclasspath.bat" %%i
java -Xms512m -Xmx1024m -cp "%CLASSPATH%" "com.googlecode.dex2jar.tools.to.Do" %*
java -Xms512m -Xmx1024m -cp "%CLASSPATH%" "com.googlecode.dex2jar.tools.AsmVerify" %*

View File

@ -20,4 +20,4 @@ for k in "$PRGDIR"/lib/*.jar
do
_classpath="${_classpath}:${k}"
done
java -Xms512m -Xmx1024m -classpath "${_classpath}" "com.googlecode.dex2jar.tools.to.Do" $@
java -Xms512m -Xmx1024m -classpath "${_classpath}" "com.googlecode.dex2jar.tools.AsmVerify" $@

View File

@ -2,4 +2,4 @@
set CLASSPATH=
FOR %%i IN ("%~dp0lib\*.jar") DO CALL "%~dp0setclasspath.bat" %%i
java -Xms512m -Xmx1024m -cp "%CLASSPATH%" "com.googlecode.dex2jar.tools.to.Do" %*
java -Xms512m -Xmx1024m -cp "%CLASSPATH%" "com.googlecode.dex2jar.tools.Jar2Dex" %*

View File

@ -20,4 +20,4 @@ for k in "$PRGDIR"/lib/*.jar
do
_classpath="${_classpath}:${k}"
done
java -Xms512m -Xmx1024m -classpath "${_classpath}" "com.googlecode.dex2jar.tools.to.Do" $@
java -Xms512m -Xmx1024m -classpath "${_classpath}" "com.googlecode.dex2jar.tools.Jar2Dex" $@

View File

@ -32,6 +32,5 @@ public class BinGen {
FileUtils.writeStringToFile(new File(binDir, key.toString() + ".bat"),
bat.replaceAll("__@class_name@__", p.getProperty(name)), "UTF-8");
}
System.out.println("Done.");
}
}

View File

@ -0,0 +1,186 @@
package com.googlecode.dex2jar.tools;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TryCatchBlockNode;
import org.objectweb.asm.tree.analysis.Analyzer;
import org.objectweb.asm.tree.analysis.BasicVerifier;
import org.objectweb.asm.tree.analysis.Frame;
import org.objectweb.asm.util.AbstractVisitor;
import org.objectweb.asm.util.CheckClassAdapter;
import org.objectweb.asm.util.TraceMethodVisitor;
public class AsmVerify {
private static final Options options = new Options();;
static {
options.addOption(new Option("d", "detail", false, "print detail error message"));
}
/**
* Prints the usage message.
*/
private static void usage() {
HelpFormatter formatter = new HelpFormatter();
formatter.setOptionComparator(new Comparator<Option>() {
@Override
public int compare(Option o1, Option o2) {
return o1.getOpt().compareTo(o2.getOpt());
}
});
formatter.printHelp("d2j-asm-verify [options] <jar0> [jar1 ... jarN]", "verify .class in jar", options, "");
}
/**
* @param args
* @throws IOException
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
public static void main(String[] args) throws IOException, IllegalArgumentException, IllegalAccessException {
CommandLineParser parser = new PosixParser();
CommandLine commandLine;
try {
commandLine = parser.parse(options, args);
} catch (ParseException ex) {
usage();
return;
}
String[] remainingArgs = commandLine.getArgs();
if (remainingArgs.length < 1) {
usage();
return;
}
List<File> files = new ArrayList<File>();
for (String fn : remainingArgs) {
File file = new File(fn);
if (!file.exists() || !file.isFile()) {
System.err.println(fn + " is not exists");
usage();
return;
}
files.add(file);
}
boolean detail = false;
for (Option option : commandLine.getOptions()) {
String opt = option.getOpt();
switch (opt.charAt(0)) {
case 'd':
detail = true;
break;
}
}
for (File file : files) {
ZipFile zip = null;
try {
zip = new ZipFile(file);
} catch (IOException e1) {
System.err.println(file + " is not a validate zip file");
if (detail) {
e1.printStackTrace(System.err);
}
usage();
return;
}
for (Enumeration<? extends ZipEntry> e = zip.entries(); e.hasMoreElements();) {
ZipEntry zipEntry = e.nextElement();
System.out.println("Verify jar " + zipEntry.getName());
if (!zipEntry.isDirectory() && zipEntry.getName().endsWith(".class")) {
InputStream is = zip.getInputStream(zipEntry);
ClassReader cr = new ClassReader(is);
ClassNode cn = new ClassNode();
cr.accept(new CheckClassAdapter(cn, false), ClassReader.SKIP_DEBUG);
List methods = cn.methods;
for (int i = 0; i < methods.size(); ++i) {
MethodNode method = (MethodNode) methods.get(i);
BasicVerifier verifier = new BasicVerifier();
Analyzer a = new Analyzer(verifier);
try {
a.analyze(cn.name, method);
} catch (Exception ex) {
System.err.println("Error verify method " + method.name + " " + method.desc);
if (detail) {
printAnalyzerResult(method, a, new PrintWriter(System.err));
}
}
}
}
}
}
}
static void printAnalyzerResult(MethodNode method, Analyzer a, final PrintWriter pw)
throws IllegalArgumentException, IllegalAccessException {
Frame[] frames = a.getFrames();
TraceMethodVisitor mv = new TraceMethodVisitor();
String format = "%05d %-" + (method.maxStack + method.maxLocals + 6) + "s|%s";
for (int j = 0; j < method.instructions.size(); ++j) {
method.instructions.get(j).accept(mv);
StringBuffer s = new StringBuffer();
Frame f = frames[j];
if (f == null) {
s.append('?');
} else {
for (int k = 0; k < f.getLocals(); ++k) {
s.append(getShortName(f.getLocal(k).toString()));
}
s.append(" : ");
for (int k = 0; k < f.getStackSize(); ++k) {
s.append(getShortName(f.getStack(k).toString()));
}
}
pw.printf(format, j, s, buf.get(mv)); // mv.text.get(j));
}
for (int j = 0; j < method.tryCatchBlocks.size(); ++j) {
((TryCatchBlockNode) method.tryCatchBlocks.get(j)).accept(mv);
pw.print(" " + buf.get(mv));
}
pw.println();
pw.flush();
}
private static String getShortName(final String name) {
int n = name.lastIndexOf('/');
return n == -1 ? name : "o";
}
static Field buf;
static {
try {
buf = AbstractVisitor.class.getDeclaredField("buf");
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
buf.setAccessible(true);
}
}

View File

@ -0,0 +1,115 @@
package com.googlecode.dex2jar.tools;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.io.FilenameUtils;
public class Jar2Dex {
private static final Options options = new Options();;
static {
options.addOption(new Option("o", "output", true,
"output .dex file, default is $current_dir/[jar-name]-jar2dex.dex"));
options.addOption(new Option("f", "force", false, "force overwrite"));
}
/**
* Prints the usage message.
*/
private static void usage() {
HelpFormatter formatter = new HelpFormatter();
formatter.setOptionComparator(new Comparator<Option>() {
@Override
public int compare(Option o1, Option o2) {
return o1.getOpt().compareTo(o2.getOpt());
}
});
formatter.printHelp("d2j-jar2dex [options] <dir>", "invoke dx to convert jar to dex", options, "");
}
/**
* @param args
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws ClassNotFoundException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws IOException
*/
public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException, ClassNotFoundException, NoSuchMethodException, SecurityException, IOException {
CommandLineParser parser = new PosixParser();
CommandLine commandLine;
try {
commandLine = parser.parse(options, args);
} catch (ParseException ex) {
usage();
return;
}
String[] remainingArgs = commandLine.getArgs();
if (remainingArgs.length != 1) {
usage();
return;
}
File jar = new File(remainingArgs[0]);
if (!jar.exists() || !jar.isFile()) {
System.err.println(jar + " is not exists");
usage();
return;
}
File output = null;
boolean force = false;
for (Option option : commandLine.getOptions()) {
String opt = option.getOpt();
switch (opt.charAt(0)) {
case 'o': {
String v = commandLine.getOptionValue("o");
if (v != null) {
output = new File(v);
}
}
break;
case 'f': {
force = true;
}
break;
}
}
if (output == null) {
output = new File(FilenameUtils.getBaseName(jar.getName()) + "-jar2dex.dex");
}
if (output.exists() && !force) {
System.err.println(output + " exists, use --force to overwrite");
usage();
return;
}
Class<?> c = Class.forName("com.android.dx.command.Main");
Method m = c.getMethod("main", String[].class);
List<String> ps = new ArrayList<String>();
ps.addAll(Arrays.asList("--dex", "--no-strict", "--output=" + output.getCanonicalPath(), jar.getCanonicalPath()));
System.out.println("call com.android.dx.command.Main.main" + ps);
m.invoke(null, new Object[] { ps.toArray(new String[0]) });
}
}

View File

@ -27,7 +27,7 @@ public class Jar2Jasmin {
static {
options.addOption(new Option("d", "debug", false, "disassemble debug info"));
options.addOption(new Option("o", "output", true,
"output dir of .j files, default is $current_dir/[jar-name]-2jasmin"));
"output dir of .j files, default is $current_dir/[jar-name]-jar2jasmin/"));
options.addOption(new Option("f", "force", false, "force overwrite"));
}
@ -95,7 +95,7 @@ public class Jar2Jasmin {
}
if (output == null) {
output = new File(FilenameUtils.getBaseName(jar.getName()) + "2jasmin/");
output = new File(FilenameUtils.getBaseName(jar.getName()) + "-jar2jasmin/");
}
if (output.exists() && !force) {
@ -134,6 +134,5 @@ public class Jar2Jasmin {
}
}
}
System.out.println("Done.");
}
}

View File

@ -17,7 +17,6 @@ import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
public class Jasmin2Jar {
@ -98,7 +97,7 @@ public class Jasmin2Jar {
}
}
if (output == null) {
output = new File(FilenameUtils.getBaseName(dir.getName()) + "-jasmin2jar.jar");
output = new File(dir.getName() + "-jasmin2jar.jar");
}
if (output.exists() && !force) {
@ -106,6 +105,9 @@ public class Jasmin2Jar {
usage();
return;
}
System.out.println("assemble " + dir + " to " + output);
Class<?> clz = Class.forName("jasmin.ClassFile");
Method readJasmin = clz.getMethod("readJasmin", Reader.class, String.class, boolean.class);
Method errorCount = clz.getMethod("errorCount");

View File

@ -10,8 +10,8 @@ d2j-dex-dump=com.googlecode.dex2jar.util.Dump
# from dex-tool
d2j-apk-extract=com.googlecode.dex2jar.tools.to.Do
d2j-jar2dex=com.googlecode.dex2jar.tools.to.Do
d2j-jar-verify=com.googlecode.dex2jar.tools.to.Do
d2j-jar2dex=com.googlecode.dex2jar.tools.Jar2Dex
d2j-asm-verify=com.googlecode.dex2jar.tools.AsmVerify
d2j-jar2jasmin=com.googlecode.dex2jar.tools.Jar2Jasmin
d2j-jasmin2jar=com.googlecode.dex2jar.tools.Jasmin2Jar
d2j-apk-sign=com.googlecode.dex2jar.tools.to.Do