mirror of
https://github.com/revanced/smali.git
synced 2025-05-09 02:44: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>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<!--<plugin>
|
||||
<groupId>org.jf</groupId>
|
||||
<artifactId>maven-smali-plugin</artifactId>
|
||||
<executions>
|
||||
@ -48,12 +48,12 @@
|
||||
<argument>-classpath</argument>
|
||||
<classpath/>
|
||||
<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/out</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugin>-->
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
@ -80,5 +80,10 @@
|
||||
<artifactId>dexlib</artifactId>
|
||||
<version>0.91-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-cli</groupId>
|
||||
<artifactId>commons-cli</artifactId>
|
||||
<version>1.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -36,7 +36,7 @@ public class LongRenderer implements AttributeRenderer {
|
||||
if (l < 0) {
|
||||
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) {
|
||||
|
@ -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.dexlib.DexFile;
|
||||
import org.jf.dexlib.ClassDefItem;
|
||||
import org.apache.commons.cli.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
@ -41,12 +42,46 @@ import java.net.URL;
|
||||
public class baksmali {
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
if (args.length < 2) {
|
||||
throw new UsageException();
|
||||
Options options = new Options();
|
||||
|
||||
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);
|
||||
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.Util.ByteArrayAnnotatedOutput;
|
||||
import org.apache.commons.cli.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
public class dump {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
Options options = new Options();
|
||||
|
||||
if (args.length < 2) {
|
||||
throw new UsageException();
|
||||
Option helpOption = OptionBuilder.withLongOpt("help")
|
||||
.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];
|
||||
String outFile = args[1];
|
||||
if (commandLine.hasOption("?")) {
|
||||
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);
|
||||
if (!dexFileFile.exists()) {
|
||||
@ -52,20 +120,35 @@ public class dump {
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
|
||||
DexFile dexFile = new DexFile(new File(dexFileName), true);
|
||||
DexFile dexFile = new DexFile(new File(dexFileName), !unsignedRegisters);
|
||||
|
||||
ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput();
|
||||
out.enableAnnotations(120, true);
|
||||
|
||||
if (sortDex) {
|
||||
dexFile.place(true);
|
||||
}
|
||||
dexFile.writeTo(out);
|
||||
|
||||
|
||||
out.finishAnnotating();
|
||||
|
||||
FileWriter writer = null;
|
||||
try {
|
||||
writer = new FileWriter(outFile);
|
||||
writer = new FileWriter(outputDumpName);
|
||||
out.writeAnnotationsTo(writer);
|
||||
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) {
|
||||
if (writer != null) {
|
||||
writer.close();
|
||||
@ -73,4 +156,13 @@ public class dump {
|
||||
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;
|
||||
|
||||
import org.apache.commons.cli.*;
|
||||
|
||||
/**
|
||||
* Main class for baksmali. It recognizes enough options to be able to dispatch
|
||||
* to the right "actual" main.
|
||||
@ -25,20 +27,6 @@ public class main {
|
||||
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.
|
||||
*/
|
||||
@ -50,73 +38,93 @@ public class main {
|
||||
* Run!
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
boolean gotCmd = false;
|
||||
boolean showUsage = false;
|
||||
Options options = new Options();
|
||||
|
||||
|
||||
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 {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
String arg = args[i];
|
||||
if (arg.equals("--") || !arg.startsWith("--")) {
|
||||
gotCmd = false;
|
||||
showUsage = true;
|
||||
break;
|
||||
}
|
||||
parser.parse(options, new String[]{args[0]});
|
||||
} catch (ParseException ex) {
|
||||
printHelp(options);
|
||||
return;
|
||||
}
|
||||
|
||||
gotCmd = true;
|
||||
if (arg.equals("--disassemble")) {
|
||||
baksmali.main(without(args, i));
|
||||
break;
|
||||
} else if (arg.equals("--dump")) {
|
||||
dump.main(without(args, i));
|
||||
break;
|
||||
} else if (arg.equals("--version")) {
|
||||
version();
|
||||
break;
|
||||
} else if (arg.equals("--help")) {
|
||||
showUsage = true;
|
||||
break;
|
||||
} else {
|
||||
gotCmd = false;
|
||||
}
|
||||
try
|
||||
{
|
||||
|
||||
String command = mainCommand.getSelected();
|
||||
if (command.equals("?")) {
|
||||
printHelp(options);
|
||||
return;
|
||||
}
|
||||
|
||||
if (command.equals("v")) {
|
||||
version();
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
System.err.println("\nUNEXPECTED TOP-LEVEL EXCEPTION:");
|
||||
ex.printStackTrace();
|
||||
System.exit(2);
|
||||
System.exit(1);
|
||||
} catch (Throwable ex) {
|
||||
System.err.println("\nUNEXPECTED TOP-LEVEL ERROR:");
|
||||
ex.printStackTrace();
|
||||
System.exit(3);
|
||||
System.exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (!gotCmd) {
|
||||
System.err.println("error: no command specified");
|
||||
showUsage = true;
|
||||
}
|
||||
|
||||
if (showUsage) {
|
||||
usage();
|
||||
System.exit(1);
|
||||
}
|
||||
/**
|
||||
* Prints the usage message.
|
||||
*/
|
||||
private static void printHelp(Options options) {
|
||||
HelpFormatter formatter = new HelpFormatter();
|
||||
formatter.printHelp("java -jar baksmali.jar <command> [command-args]",
|
||||
"use <command> --help to see the options each command accepts", options, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the version message.
|
||||
*/
|
||||
private static void version() {
|
||||
System.err.println("baksmali version " + VERSION);
|
||||
System.err.println("baksmali v" + VERSION);
|
||||
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
|
||||
* element.
|
||||
|
Loading…
x
Reference in New Issue
Block a user