main.java revision c894b9658c69a014ed1f57732b066a180218d126
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.jf.baksmali;
18
19import org.apache.commons.cli.*;
20import org.jf.dexlib.DexFile;
21import org.jf.baksmali.Renderers.*;
22import org.antlr.stringtemplate.StringTemplateGroup;
23
24import java.io.File;
25import java.io.InputStream;
26import java.io.InputStreamReader;
27import java.io.IOException;
28
29public class main {
30
31    public static final String VERSION = "0.91";
32
33    private static final Options options;
34
35    static {
36        options = new Options();
37        buildOptions();
38    }
39
40    /**
41     * This class is uninstantiable.
42     */
43    private main() {
44    }
45
46    /**
47     * Run!
48     */
49    public static void main(String[] args) {
50        CommandLineParser parser = new PosixParser();
51        CommandLine commandLine;
52
53        try {
54            commandLine = parser.parse(options, args);
55        } catch (ParseException ex) {
56            usage();
57            return;
58        }
59
60        boolean disassemble = true;
61        boolean doDump = false;
62        boolean write = false;
63        boolean sort = false;
64        boolean fixRegisters = false;
65
66        String outputDirectory = "out";
67        String dumpFileName = null;
68        String outputDexFileName = null;
69        String inputDexFileName = null;
70
71        String[] remainingArgs = commandLine.getArgs();
72
73        if (commandLine.hasOption("v")) {
74            version();
75            return;
76        }
77
78        if (commandLine.hasOption("?")) {
79            usage();
80            return;
81        }
82
83        if (remainingArgs.length != 1) {
84            usage();
85            return;
86        }
87
88        inputDexFileName = remainingArgs[0];
89
90        if (commandLine.hasOption("d")) {
91            doDump = true;
92            dumpFileName = commandLine.getOptionValue("d", inputDexFileName + ".dump");
93        }
94
95        if (commandLine.hasOption("D")) {
96            doDump = true;
97            disassemble = false;
98            dumpFileName = commandLine.getOptionValue("d", inputDexFileName + ".dump");
99        }
100
101        if (commandLine.hasOption("w")) {
102            write = true;
103            outputDexFileName = commandLine.getOptionValue("w");
104        }
105
106        if (commandLine.hasOption("o")) {
107            outputDirectory = commandLine.getOptionValue("o");
108        }
109
110        if (commandLine.hasOption("s")) {
111            sort = true;
112        }
113
114        if (commandLine.hasOption("f")) {
115            fixRegisters = true;
116        }
117
118        try {
119            File dexFileFile = new File(inputDexFileName);
120            if (!dexFileFile.exists()) {
121                System.err.println("Can't find the file " + inputDexFileName);
122                System.exit(1);
123            }
124
125            //Read in and parse the dex file
126            DexFile dexFile = new DexFile(dexFileFile, !fixRegisters);
127
128            if (disassemble) {
129                baksmali.disassembleDexFile(dexFile, outputDirectory);
130            }
131
132            if (doDump || write) {
133                try
134                {
135                    dump.dump(dexFile, dumpFileName, outputDexFileName, sort);
136                }catch (IOException ex) {
137                    System.err.println("Error occured while writing dump file");
138                    ex.printStackTrace();
139                }
140            }
141        } catch (RuntimeException ex) {
142            System.err.println("\n\nUNEXPECTED TOP-LEVEL EXCEPTION:");
143            ex.printStackTrace();
144            System.exit(1);
145        } catch (Throwable ex) {
146            System.err.println("\n\nUNEXPECTED TOP-LEVEL ERROR:");
147            ex.printStackTrace();
148            System.exit(1);
149        }
150    }
151
152    /**
153     * Prints the usage message.
154     */
155    private static void usage() {
156        HelpFormatter formatter = new HelpFormatter();
157        formatter.printHelp("java -jar baksmali.jar [options] <dex-file>",
158                "disassembles and/or dumps a dex file", options, "");
159    }
160
161    /**
162     * Prints the version message.
163     */
164    private static void version() {
165        System.out.println("baksmali " + VERSION + " (http://smali.googlecode.com)");
166        System.out.println("Copyright (C) 2009 Ben Gruver");
167        System.out.println("BSD license (http://www.opensource.org/licenses/bsd-license.php)");
168        System.exit(0);
169    }
170
171    private static void buildOptions() {
172        Option versionOption = OptionBuilder.withLongOpt("version")
173                .withDescription("prints the version then exits")
174                .create("v");
175
176        Option helpOption = OptionBuilder.withLongOpt("help")
177                .withDescription("prints the help message then exits")
178                .create("?");
179
180        Option dumpOption = OptionBuilder.withLongOpt("dump-to")
181                .withDescription("dumps the given dex file into a single annotated dump file named FILE (<dexfile>.dump by default), along with the normal disassembly.")
182                .hasOptionalArg()
183                .withArgName("FILE")
184                .create("d");
185
186        Option dumpOnlyOption = OptionBuilder.withLongOpt("dump-only")
187                .withDescription("dumps the given dex file into a single annotated dump file named FILE (<dexfile>.dump by default), and does not generate the disassembly")
188                .hasOptionalArg()
189                .withArgName("FILE")
190                .create("D");
191
192        Option writeDexOption = OptionBuilder.withLongOpt("write-dex")
193                .withDescription("additionally rewrites the input dex file to FILE")
194                .hasArg()
195                .withArgName("FILE")
196                .create("w");
197
198        Option outputDirOption = OptionBuilder.withLongOpt("output")
199                .withDescription("the directory where the disassembled files will be placed. The default is out")
200                .hasArg()
201                .withArgName("DIR")
202                .create("o");
203
204        Option sortOption = OptionBuilder.withLongOpt("sort")
205                .withDescription("sort the items in the dex file into a canonical order before dumping/writing")
206                .create("s");
207
208        Option fixSignedRegisterOption = OptionBuilder.withLongOpt("fix-signed-registers")
209                .withDescription("when dumping or rewriting, fix any registers in the debug info that are encoded as a signed value")
210                .create("f");
211
212        OptionGroup dumpCommand = new OptionGroup();
213        dumpCommand.addOption(dumpOption);
214        dumpCommand.addOption(dumpOnlyOption);
215
216        options.addOption(versionOption);
217        options.addOption(helpOption);
218        options.addOptionGroup(dumpCommand);
219        options.addOption(writeDexOption);
220        options.addOption(outputDirOption);
221        options.addOption(sortOption);
222        options.addOption(fixSignedRegisterOption);
223    }
224}