mirror of
https://github.com/revanced/smali.git
synced 2025-05-09 10:54:29 +02:00
- Redid the option parsing logic to use the apache commons cli library
- Added options to the dump command, to help with dumping and comparing 2 dex files git-svn-id: https://smali.googlecode.com/svn/trunk@210 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
parent
ec857fcecd
commit
d166b746b9
@ -12,7 +12,7 @@
|
|||||||
</parent>
|
</parent>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<!--<plugin>
|
||||||
<groupId>org.jf</groupId>
|
<groupId>org.jf</groupId>
|
||||||
<artifactId>maven-smali-plugin</artifactId>
|
<artifactId>maven-smali-plugin</artifactId>
|
||||||
<executions>
|
<executions>
|
||||||
@ -48,12 +48,12 @@
|
|||||||
<argument>-classpath</argument>
|
<argument>-classpath</argument>
|
||||||
<classpath/>
|
<classpath/>
|
||||||
<argument>org.jf.baksmali.main</argument>
|
<argument>org.jf.baksmali.main</argument>
|
||||||
<argument>--disassemble</argument>
|
<argument>-dis</argument>
|
||||||
<argument>${project.build.directory}/test/classes.dex</argument>
|
<argument>${project.build.directory}/test/classes.dex</argument>
|
||||||
<argument>${project.build.directory}/test/out</argument>
|
<argument>${project.build.directory}/test/out</argument>
|
||||||
</arguments>
|
</arguments>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>-->
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
@ -80,5 +80,10 @@
|
|||||||
<artifactId>dexlib</artifactId>
|
<artifactId>dexlib</artifactId>
|
||||||
<version>0.91-SNAPSHOT</version>
|
<version>0.91-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-cli</groupId>
|
||||||
|
<artifactId>commons-cli</artifactId>
|
||||||
|
<version>1.2</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
@ -36,7 +36,7 @@ public class LongRenderer implements AttributeRenderer {
|
|||||||
if (l < 0) {
|
if (l < 0) {
|
||||||
return "-0x" + Long.toHexString(-1 * l) + "L";
|
return "-0x" + Long.toHexString(-1 * l) + "L";
|
||||||
}
|
}
|
||||||
return "0x" + Long.toHexString((Long)o) + "L";
|
return "0x" + Long.toHexString(l) + "L";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString(Object o, String s) {
|
public String toString(Object o, String s) {
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2008 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jf.baksmali;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple exception class used to communicate that the command-line tool
|
|
||||||
* should print the usage message.
|
|
||||||
*/
|
|
||||||
public class UsageException extends RuntimeException {
|
|
||||||
// This space intentionally left blank.
|
|
||||||
}
|
|
@ -34,6 +34,7 @@ import org.jf.baksmali.Adaptors.ClassDefinition;
|
|||||||
import org.jf.baksmali.Renderers.*;
|
import org.jf.baksmali.Renderers.*;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.ClassDefItem;
|
import org.jf.dexlib.ClassDefItem;
|
||||||
|
import org.apache.commons.cli.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@ -41,12 +42,46 @@ import java.net.URL;
|
|||||||
public class baksmali {
|
public class baksmali {
|
||||||
public static void main(String[] args) throws Exception
|
public static void main(String[] args) throws Exception
|
||||||
{
|
{
|
||||||
if (args.length < 2) {
|
Options options = new Options();
|
||||||
throw new UsageException();
|
|
||||||
|
Option helpOption = OptionBuilder.withLongOpt("help")
|
||||||
|
.withDescription("prints the usage information for the -dis command")
|
||||||
|
.create("?");
|
||||||
|
|
||||||
|
Option outputDirOption = OptionBuilder.withLongOpt("output")
|
||||||
|
.withDescription("the directory where the disassembled files will be placed. The default is out")
|
||||||
|
.hasArg()
|
||||||
|
.withArgName("DIR")
|
||||||
|
.create("out");
|
||||||
|
|
||||||
|
options.addOption(helpOption);
|
||||||
|
options.addOption(outputDirOption);
|
||||||
|
|
||||||
|
CommandLineParser parser = new PosixParser();
|
||||||
|
CommandLine commandLine;
|
||||||
|
|
||||||
|
try {
|
||||||
|
commandLine = parser.parse(options, args);
|
||||||
|
} catch (ParseException ex) {
|
||||||
|
printHelp(options);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commandLine.hasOption("?")) {
|
||||||
|
printHelp(options);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String dexFileName = args[0];
|
|
||||||
String outputDirName = args[1];
|
String[] leftover = commandLine.getArgs();
|
||||||
|
|
||||||
|
if (leftover.length != 1) {
|
||||||
|
printHelp(options);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String dexFileName = leftover[0];
|
||||||
|
String outputDirName = commandLine.getOptionValue("out", "out");
|
||||||
|
|
||||||
File dexFileFile = new File(dexFileName);
|
File dexFileFile = new File(dexFileName);
|
||||||
if (!dexFileFile.exists()) {
|
if (!dexFileFile.exists()) {
|
||||||
@ -128,4 +163,13 @@ public class baksmali {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the usage message.
|
||||||
|
*/
|
||||||
|
private static void printHelp(Options options) {
|
||||||
|
HelpFormatter formatter = new HelpFormatter();
|
||||||
|
formatter.printHelp("java -jar baksmali.jar -dis [-out <DIR>] <dexfile>",
|
||||||
|
"Disassembles the given dex file", options, "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,21 +30,89 @@ package org.jf.baksmali;
|
|||||||
|
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Util.ByteArrayAnnotatedOutput;
|
import org.jf.dexlib.Util.ByteArrayAnnotatedOutput;
|
||||||
|
import org.apache.commons.cli.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
|
||||||
public class dump {
|
public class dump {
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
|
Options options = new Options();
|
||||||
|
|
||||||
if (args.length < 2) {
|
Option helpOption = OptionBuilder.withLongOpt("help")
|
||||||
throw new UsageException();
|
.withDescription("prints the usage information for the --dump command")
|
||||||
|
.create("?");
|
||||||
|
|
||||||
|
Option outputFileOption = OptionBuilder.withLongOpt("output")
|
||||||
|
.withDescription("the file where the dump will be written. The default is <dexfile>.dump, where <dexfile> is the name of the given dex file")
|
||||||
|
.hasArg()
|
||||||
|
.withArgName("FILE")
|
||||||
|
.create("out");
|
||||||
|
|
||||||
|
Option writeDexFileOption = OptionBuilder.withLongOpt("write-dex-file")
|
||||||
|
.withDescription("optionally re-write out the dex file to the given file")
|
||||||
|
.hasArg()
|
||||||
|
.withArgName("FILE")
|
||||||
|
.create("writedex");
|
||||||
|
|
||||||
|
Option sortDexFileOption = OptionBuilder.withLongOpt("sort-dex-file")
|
||||||
|
.withDescription("optionally sorts the items in the dex file before dumping/writing it")
|
||||||
|
.create("sortdex");
|
||||||
|
|
||||||
|
Option unsignedRegisterOption = OptionBuilder.withLongOpt("unsigned-registers")
|
||||||
|
.withDescription("always write the registers in the debug info as unsigned. By default we keep the same signed/unsigned format as what was in the original file")
|
||||||
|
.create("unsigned");
|
||||||
|
|
||||||
|
options.addOption(helpOption);
|
||||||
|
options.addOption(outputFileOption);
|
||||||
|
options.addOption(writeDexFileOption);
|
||||||
|
options.addOption(sortDexFileOption);
|
||||||
|
options.addOption(unsignedRegisterOption);
|
||||||
|
|
||||||
|
CommandLineParser parser = new PosixParser();
|
||||||
|
CommandLine commandLine;
|
||||||
|
|
||||||
|
try {
|
||||||
|
commandLine = parser.parse(options, args);
|
||||||
|
} catch (ParseException ex) {
|
||||||
|
printHelp(options);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String dexFileName = args[0];
|
if (commandLine.hasOption("?")) {
|
||||||
String outFile = args[1];
|
printHelp(options);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] leftover = commandLine.getArgs();
|
||||||
|
|
||||||
|
if (leftover.length != 1) {
|
||||||
|
printHelp(options);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String dexFileName = leftover[0];
|
||||||
|
String outputDumpName = commandLine.getOptionValue("out", dexFileName + ".dump");
|
||||||
|
|
||||||
|
boolean writeDex = false;
|
||||||
|
String outputDexName = null;
|
||||||
|
if (commandLine.hasOption("writedex")) {
|
||||||
|
writeDex = true;
|
||||||
|
outputDexName = commandLine.getOptionValue("writedex");
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean sortDex = false;
|
||||||
|
if (commandLine.hasOption("sortdex")) {
|
||||||
|
sortDex = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean unsignedRegisters = false;
|
||||||
|
if (commandLine.hasOption("unsigned")) {
|
||||||
|
unsignedRegisters = true;
|
||||||
|
}
|
||||||
|
|
||||||
File dexFileFile = new File(dexFileName);
|
File dexFileFile = new File(dexFileName);
|
||||||
if (!dexFileFile.exists()) {
|
if (!dexFileFile.exists()) {
|
||||||
@ -52,20 +120,35 @@ public class dump {
|
|||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DexFile dexFile = new DexFile(new File(dexFileName), !unsignedRegisters);
|
||||||
DexFile dexFile = new DexFile(new File(dexFileName), true);
|
|
||||||
|
|
||||||
ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput();
|
ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput();
|
||||||
out.enableAnnotations(120, true);
|
out.enableAnnotations(120, true);
|
||||||
|
|
||||||
|
if (sortDex) {
|
||||||
|
dexFile.place(true);
|
||||||
|
}
|
||||||
dexFile.writeTo(out);
|
dexFile.writeTo(out);
|
||||||
|
|
||||||
|
|
||||||
out.finishAnnotating();
|
out.finishAnnotating();
|
||||||
|
|
||||||
FileWriter writer = null;
|
FileWriter writer = null;
|
||||||
try {
|
try {
|
||||||
writer = new FileWriter(outFile);
|
writer = new FileWriter(outputDumpName);
|
||||||
out.writeAnnotationsTo(writer);
|
out.writeAnnotationsTo(writer);
|
||||||
writer.close();
|
writer.close();
|
||||||
|
|
||||||
|
if (writeDex) {
|
||||||
|
byte[] bytes = out.toByteArray();
|
||||||
|
|
||||||
|
DexFile.calcSignature(bytes);
|
||||||
|
DexFile.calcChecksum(bytes);
|
||||||
|
|
||||||
|
FileOutputStream fileOutputStream = new FileOutputStream(outputDexName);
|
||||||
|
fileOutputStream.write(bytes);
|
||||||
|
fileOutputStream.close();
|
||||||
|
}
|
||||||
}catch (IOException ex) {
|
}catch (IOException ex) {
|
||||||
if (writer != null) {
|
if (writer != null) {
|
||||||
writer.close();
|
writer.close();
|
||||||
@ -73,4 +156,13 @@ public class dump {
|
|||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the usage message.
|
||||||
|
*/
|
||||||
|
private static void printHelp(Options options) {
|
||||||
|
HelpFormatter formatter = new HelpFormatter();
|
||||||
|
formatter.printHelp("java -jar baksmali.jar -dump [options] <dexfile>",
|
||||||
|
"Dumps the given dex file", options, "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package org.jf.baksmali;
|
package org.jf.baksmali;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main class for baksmali. It recognizes enough options to be able to dispatch
|
* Main class for baksmali. It recognizes enough options to be able to dispatch
|
||||||
* to the right "actual" main.
|
* to the right "actual" main.
|
||||||
@ -25,20 +27,6 @@ public class main {
|
|||||||
public static final String VERSION = "0.91";
|
public static final String VERSION = "0.91";
|
||||||
|
|
||||||
|
|
||||||
private static String USAGE_MESSAGE =
|
|
||||||
"usage:\n" +
|
|
||||||
" java -jar baksmali.jar --disassemble <.dex file> <output folder>\n" +
|
|
||||||
" disassembles the given dex file into a set of .smali files\n" +
|
|
||||||
" in the given folder\n" +
|
|
||||||
" java -jar baksmali.jar --dump <.dex file> <dump file>\n" +
|
|
||||||
" dumps the given dex file to a single annotated dump file\n" +
|
|
||||||
" that follows the order and structure of the dex file.\n" +
|
|
||||||
" java -jar baksmali.jar --version\n" +
|
|
||||||
" Print the version of this tool (" + VERSION +
|
|
||||||
").\n" +
|
|
||||||
" java -jar baksmali.jar --help\n" +
|
|
||||||
" Print this message.";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is uninstantiable.
|
* This class is uninstantiable.
|
||||||
*/
|
*/
|
||||||
@ -50,73 +38,93 @@ public class main {
|
|||||||
* Run!
|
* Run!
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
boolean gotCmd = false;
|
Options options = new Options();
|
||||||
boolean showUsage = false;
|
|
||||||
|
|
||||||
|
Option versionOption = OptionBuilder.withLongOpt("version")
|
||||||
|
.withDescription("prints the version")
|
||||||
|
.create("v");
|
||||||
|
|
||||||
|
Option helpOption = OptionBuilder.withLongOpt("help")
|
||||||
|
.withDescription("prints the help message")
|
||||||
|
.create("?");
|
||||||
|
|
||||||
|
Option disassembleOption = OptionBuilder.withLongOpt("disassemble")
|
||||||
|
.withDescription("disassembles a dex file into individual files for each class that are placed into a folder structure that matches the package structure of the classes.")
|
||||||
|
.create("dis");
|
||||||
|
|
||||||
|
Option dumpOption = OptionBuilder.withLongOpt("dump")
|
||||||
|
.withDescription("Dumps a dex file into a single annotated dump file named FILE")
|
||||||
|
.create("dump");
|
||||||
|
|
||||||
|
OptionGroup mainCommand = new OptionGroup();
|
||||||
|
mainCommand.addOption(versionOption);
|
||||||
|
mainCommand.addOption(helpOption);
|
||||||
|
mainCommand.addOption(disassembleOption);
|
||||||
|
mainCommand.addOption(dumpOption);
|
||||||
|
mainCommand.setRequired(true);
|
||||||
|
|
||||||
|
options.addOptionGroup(mainCommand);
|
||||||
|
|
||||||
|
CommandLineParser parser = new PosixParser();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (int i = 0; i < args.length; i++) {
|
parser.parse(options, new String[]{args[0]});
|
||||||
String arg = args[i];
|
} catch (ParseException ex) {
|
||||||
if (arg.equals("--") || !arg.startsWith("--")) {
|
printHelp(options);
|
||||||
gotCmd = false;
|
return;
|
||||||
showUsage = true;
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
gotCmd = true;
|
try
|
||||||
if (arg.equals("--disassemble")) {
|
{
|
||||||
baksmali.main(without(args, i));
|
|
||||||
break;
|
String command = mainCommand.getSelected();
|
||||||
} else if (arg.equals("--dump")) {
|
if (command.equals("?")) {
|
||||||
dump.main(without(args, i));
|
printHelp(options);
|
||||||
break;
|
return;
|
||||||
} else if (arg.equals("--version")) {
|
}
|
||||||
version();
|
|
||||||
break;
|
if (command.equals("v")) {
|
||||||
} else if (arg.equals("--help")) {
|
version();
|
||||||
showUsage = true;
|
return;
|
||||||
break;
|
}
|
||||||
} else {
|
|
||||||
gotCmd = false;
|
if (command.equals("dis")) {
|
||||||
}
|
baksmali.main(without(args, 0));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.equals("dump")) {
|
||||||
|
dump.main(without(args, 0));
|
||||||
}
|
}
|
||||||
} catch (UsageException ex) {
|
|
||||||
showUsage = true;
|
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
System.err.println("\nUNEXPECTED TOP-LEVEL EXCEPTION:");
|
System.err.println("\nUNEXPECTED TOP-LEVEL EXCEPTION:");
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
System.exit(2);
|
System.exit(1);
|
||||||
} catch (Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
System.err.println("\nUNEXPECTED TOP-LEVEL ERROR:");
|
System.err.println("\nUNEXPECTED TOP-LEVEL ERROR:");
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
System.exit(3);
|
System.exit(2);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!gotCmd) {
|
/**
|
||||||
System.err.println("error: no command specified");
|
* Prints the usage message.
|
||||||
showUsage = true;
|
*/
|
||||||
}
|
private static void printHelp(Options options) {
|
||||||
|
HelpFormatter formatter = new HelpFormatter();
|
||||||
if (showUsage) {
|
formatter.printHelp("java -jar baksmali.jar <command> [command-args]",
|
||||||
usage();
|
"use <command> --help to see the options each command accepts", options, "");
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints the version message.
|
* Prints the version message.
|
||||||
*/
|
*/
|
||||||
private static void version() {
|
private static void version() {
|
||||||
System.err.println("baksmali version " + VERSION);
|
System.err.println("baksmali v" + VERSION);
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints the usage message.
|
|
||||||
*/
|
|
||||||
private static void usage() {
|
|
||||||
System.err.println(USAGE_MESSAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a copy of the given args array, but without the indicated
|
* Returns a copy of the given args array, but without the indicated
|
||||||
* element.
|
* element.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user