main.java revision 9293a116b33ad0e74b6deab53e673d0c391f4ae9
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 boolean readOnly = false; 66 67 String outputDirectory = "out"; 68 String dumpFileName = null; 69 String outputDexFileName = null; 70 String inputDexFileName = null; 71 72 String[] remainingArgs = commandLine.getArgs(); 73 74 if (commandLine.hasOption("v")) { 75 version(); 76 return; 77 } 78 79 if (commandLine.hasOption("?")) { 80 usage(); 81 return; 82 } 83 84 if (remainingArgs.length != 1) { 85 usage(); 86 return; 87 } 88 89 inputDexFileName = remainingArgs[0]; 90 91 if (commandLine.hasOption("r")) { 92 readOnly = true; 93 } 94 95 if (commandLine.hasOption("d")) { 96 doDump = true; 97 dumpFileName = commandLine.getOptionValue("d", inputDexFileName + ".dump"); 98 } 99 100 if (commandLine.hasOption("D")) { 101 doDump = true; 102 disassemble = false; 103 dumpFileName = commandLine.getOptionValue("D", inputDexFileName + ".dump"); 104 } 105 106 if (commandLine.hasOption("w")) { 107 write = true; 108 outputDexFileName = commandLine.getOptionValue("w"); 109 } 110 111 if (commandLine.hasOption("o")) { 112 outputDirectory = commandLine.getOptionValue("o"); 113 } 114 115 if (commandLine.hasOption("s")) { 116 sort = true; 117 } 118 119 if (commandLine.hasOption("f")) { 120 fixRegisters = true; 121 } 122 123 try { 124 File dexFileFile = new File(inputDexFileName); 125 if (!dexFileFile.exists()) { 126 System.err.println("Can't find the file " + inputDexFileName); 127 System.exit(1); 128 } 129 130 //Read in and parse the dex file 131 DexFile dexFile = new DexFile(dexFileFile, !fixRegisters); 132 133 if (readOnly) { 134 return; 135 } 136 137 if (disassemble) { 138 baksmali.disassembleDexFile(dexFile, outputDirectory); 139 } 140 141 if (doDump || write) { 142 try 143 { 144 dump.dump(dexFile, dumpFileName, outputDexFileName, sort); 145 }catch (IOException ex) { 146 System.err.println("Error occured while writing dump file"); 147 ex.printStackTrace(); 148 } 149 } 150 } catch (RuntimeException ex) { 151 System.err.println("\n\nUNEXPECTED TOP-LEVEL EXCEPTION:"); 152 ex.printStackTrace(); 153 System.exit(1); 154 } catch (Throwable ex) { 155 System.err.println("\n\nUNEXPECTED TOP-LEVEL ERROR:"); 156 ex.printStackTrace(); 157 System.exit(1); 158 } 159 } 160 161 /** 162 * Prints the usage message. 163 */ 164 private static void usage() { 165 HelpFormatter formatter = new HelpFormatter(); 166 formatter.printHelp("java -jar baksmali.jar [options] <dex-file>", 167 "disassembles and/or dumps a dex file", options, ""); 168 } 169 170 /** 171 * Prints the version message. 172 */ 173 private static void version() { 174 System.out.println("baksmali " + VERSION + " (http://smali.googlecode.com)"); 175 System.out.println("Copyright (C) 2009 Ben Gruver"); 176 System.out.println("BSD license (http://www.opensource.org/licenses/bsd-license.php)"); 177 System.exit(0); 178 } 179 180 private static void buildOptions() { 181 Option versionOption = OptionBuilder.withLongOpt("version") 182 .withDescription("prints the version then exits") 183 .create("v"); 184 185 Option helpOption = OptionBuilder.withLongOpt("help") 186 .withDescription("prints the help message then exits") 187 .create("?"); 188 189 Option readonlyOption = OptionBuilder.withLongOpt("read-only") 190 .withDescription("reads in the dex file and then exits") 191 .create("r"); 192 193 Option dumpOption = OptionBuilder.withLongOpt("dump-to") 194 .withDescription("dumps the given dex file into a single annotated dump file named FILE (<dexfile>.dump by default), along with the normal disassembly.") 195 .hasOptionalArg() 196 .withArgName("FILE") 197 .create("d"); 198 199 Option dumpOnlyOption = OptionBuilder.withLongOpt("dump-only") 200 .withDescription("dumps the given dex file into a single annotated dump file named FILE (<dexfile>.dump by default), and does not generate the disassembly") 201 .hasOptionalArg() 202 .withArgName("FILE") 203 .create("D"); 204 205 Option writeDexOption = OptionBuilder.withLongOpt("write-dex") 206 .withDescription("additionally rewrites the input dex file to FILE") 207 .hasArg() 208 .withArgName("FILE") 209 .create("w"); 210 211 Option outputDirOption = OptionBuilder.withLongOpt("output") 212 .withDescription("the directory where the disassembled files will be placed. The default is out") 213 .hasArg() 214 .withArgName("DIR") 215 .create("o"); 216 217 Option sortOption = OptionBuilder.withLongOpt("sort") 218 .withDescription("sort the items in the dex file into a canonical order before dumping/writing") 219 .create("s"); 220 221 Option fixSignedRegisterOption = OptionBuilder.withLongOpt("fix-signed-registers") 222 .withDescription("when dumping or rewriting, fix any registers in the debug info that are encoded as a signed value") 223 .create("f"); 224 225 OptionGroup dumpCommand = new OptionGroup(); 226 dumpCommand.addOption(dumpOption); 227 dumpCommand.addOption(dumpOnlyOption); 228 dumpCommand.addOption(readonlyOption); 229 230 options.addOption(versionOption); 231 options.addOption(helpOption); 232 options.addOptionGroup(dumpCommand); 233 options.addOption(writeDexOption); 234 options.addOption(outputDirOption); 235 options.addOption(sortOption); 236 options.addOption(fixSignedRegisterOption); 237 } 238}