main.java revision 3c23129eecb7127646f2901c1b0ec3b94a83c08f
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; 28import java.util.Properties; 29 30public class main { 31 32 public static final String VERSION; 33 34 private static final Options options; 35 36 static { 37 options = new Options(); 38 buildOptions(); 39 40 InputStream templateStream = baksmali.class.getClassLoader().getResourceAsStream("baksmali.properties"); 41 Properties properties = new Properties(); 42 String version = "(unknown)"; 43 try { 44 properties.load(templateStream); 45 version = properties.getProperty("application.version"); 46 } catch (IOException ex) { 47 } 48 VERSION = version; 49 } 50 51 /** 52 * This class is uninstantiable. 53 */ 54 private main() { 55 } 56 57 /** 58 * Run! 59 */ 60 public static void main(String[] args) { 61 CommandLineParser parser = new PosixParser(); 62 CommandLine commandLine; 63 64 try { 65 commandLine = parser.parse(options, args); 66 } catch (ParseException ex) { 67 usage(); 68 return; 69 } 70 71 boolean disassemble = true; 72 boolean doDump = false; 73 boolean write = false; 74 boolean sort = false; 75 boolean fixRegisters = false; 76 boolean readOnly = false; 77 boolean noParameterRegisters = false; 78 79 String outputDirectory = "out"; 80 String dumpFileName = null; 81 String outputDexFileName = null; 82 String inputDexFileName = null; 83 84 String[] remainingArgs = commandLine.getArgs(); 85 86 if (commandLine.hasOption("v")) { 87 version(); 88 return; 89 } 90 91 if (commandLine.hasOption("?")) { 92 usage(); 93 return; 94 } 95 96 if (remainingArgs.length != 1) { 97 usage(); 98 return; 99 } 100 101 inputDexFileName = remainingArgs[0]; 102 103 if (commandLine.hasOption("r")) { 104 readOnly = true; 105 } 106 107 if (commandLine.hasOption("d")) { 108 doDump = true; 109 dumpFileName = commandLine.getOptionValue("d", inputDexFileName + ".dump"); 110 } 111 112 if (commandLine.hasOption("D")) { 113 doDump = true; 114 disassemble = false; 115 dumpFileName = commandLine.getOptionValue("D", inputDexFileName + ".dump"); 116 } 117 118 if (commandLine.hasOption("w")) { 119 write = true; 120 outputDexFileName = commandLine.getOptionValue("w"); 121 } 122 123 if (commandLine.hasOption("o")) { 124 outputDirectory = commandLine.getOptionValue("o"); 125 } 126 127 if (commandLine.hasOption("s")) { 128 sort = true; 129 } 130 131 if (commandLine.hasOption("f")) { 132 fixRegisters = true; 133 } 134 135 if (commandLine.hasOption("p")) { 136 noParameterRegisters = true; 137 } 138 139 try { 140 File dexFileFile = new File(inputDexFileName); 141 if (!dexFileFile.exists()) { 142 System.err.println("Can't find the file " + inputDexFileName); 143 System.exit(1); 144 } 145 146 //Read in and parse the dex file 147 DexFile dexFile = new DexFile(dexFileFile, !fixRegisters); 148 149 if (readOnly) { 150 return; 151 } 152 153 if (disassemble) { 154 baksmali.disassembleDexFile(dexFile, outputDirectory, noParameterRegisters); 155 } 156 157 if (doDump || write) { 158 try 159 { 160 dump.dump(dexFile, dumpFileName, outputDexFileName, sort); 161 }catch (IOException ex) { 162 System.err.println("Error occured while writing dump file"); 163 ex.printStackTrace(); 164 } 165 } 166 } catch (RuntimeException ex) { 167 System.err.println("\n\nUNEXPECTED TOP-LEVEL EXCEPTION:"); 168 ex.printStackTrace(); 169 System.exit(1); 170 } catch (Throwable ex) { 171 System.err.println("\n\nUNEXPECTED TOP-LEVEL ERROR:"); 172 ex.printStackTrace(); 173 System.exit(1); 174 } 175 } 176 177 /** 178 * Prints the usage message. 179 */ 180 private static void usage() { 181 HelpFormatter formatter = new HelpFormatter(); 182 formatter.printHelp("java -jar baksmali.jar [options] <dex-file>", 183 "disassembles and/or dumps a dex file", options, ""); 184 } 185 186 /** 187 * Prints the version message. 188 */ 189 private static void version() { 190 System.out.println("baksmali " + VERSION + " (http://smali.googlecode.com)"); 191 System.out.println("Copyright (C) 2009 Ben Gruver"); 192 System.out.println("BSD license (http://www.opensource.org/licenses/bsd-license.php)"); 193 System.exit(0); 194 } 195 196 private static void buildOptions() { 197 Option versionOption = OptionBuilder.withLongOpt("version") 198 .withDescription("prints the version then exits") 199 .create("v"); 200 201 Option helpOption = OptionBuilder.withLongOpt("help") 202 .withDescription("prints the help message then exits") 203 .create("?"); 204 205 Option readonlyOption = OptionBuilder.withLongOpt("read-only") 206 .withDescription("reads in the dex file and then exits") 207 .create("r"); 208 209 Option dumpOption = OptionBuilder.withLongOpt("dump-to") 210 .withDescription("dumps the given dex file into a single annotated dump file named FILE (<dexfile>.dump by default), along with the normal disassembly.") 211 .hasOptionalArg() 212 .withArgName("FILE") 213 .create("d"); 214 215 Option dumpOnlyOption = OptionBuilder.withLongOpt("dump-only") 216 .withDescription("dumps the given dex file into a single annotated dump file named FILE (<dexfile>.dump by default), and does not generate the disassembly") 217 .hasOptionalArg() 218 .withArgName("FILE") 219 .create("D"); 220 221 Option writeDexOption = OptionBuilder.withLongOpt("write-dex") 222 .withDescription("additionally rewrites the input dex file to FILE") 223 .hasArg() 224 .withArgName("FILE") 225 .create("w"); 226 227 Option outputDirOption = OptionBuilder.withLongOpt("output") 228 .withDescription("the directory where the disassembled files will be placed. The default is out") 229 .hasArg() 230 .withArgName("DIR") 231 .create("o"); 232 233 Option sortOption = OptionBuilder.withLongOpt("sort") 234 .withDescription("sort the items in the dex file into a canonical order before dumping/writing") 235 .create("s"); 236 237 Option fixSignedRegisterOption = OptionBuilder.withLongOpt("fix-signed-registers") 238 .withDescription("when dumping or rewriting, fix any registers in the debug info that are encoded as" + 239 " a signed value") 240 .create("f"); 241 242 Option noParameterRegistersOption = OptionBuilder.withLongOpt("no-parameter-registers") 243 .withDescription("use the v<n> syntax instead of the p<n> syntax for registers mapped to method" + 244 " parameters") 245 .create("p"); 246 247 OptionGroup dumpCommand = new OptionGroup(); 248 dumpCommand.addOption(dumpOption); 249 dumpCommand.addOption(dumpOnlyOption); 250 dumpCommand.addOption(readonlyOption); 251 252 options.addOption(versionOption); 253 options.addOption(helpOption); 254 options.addOptionGroup(dumpCommand); 255 options.addOption(writeDexOption); 256 options.addOption(outputDirOption); 257 options.addOption(sortOption); 258 options.addOption(fixSignedRegisterOption); 259 options.addOption(noParameterRegistersOption); 260 } 261}