main.java revision 5b89857df3124851183c75a134f10b6ba41512a9
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.dexlib.Util.Deodexerant; 22 23import java.io.File; 24import java.io.InputStream; 25import java.io.IOException; 26import java.util.Properties; 27 28public class main { 29 30 public static final String VERSION; 31 32 private static final Options options; 33 34 static { 35 options = new Options(); 36 buildOptions(); 37 38 InputStream templateStream = baksmali.class.getClassLoader().getResourceAsStream("baksmali.properties"); 39 Properties properties = new Properties(); 40 String version = "(unknown)"; 41 try { 42 properties.load(templateStream); 43 version = properties.getProperty("application.version"); 44 } catch (IOException ex) { 45 } 46 VERSION = version; 47 } 48 49 /** 50 * This class is uninstantiable. 51 */ 52 private main() { 53 } 54 55 /** 56 * Run! 57 */ 58 public static void main(String[] args) { 59 CommandLineParser parser = new PosixParser(); 60 CommandLine commandLine; 61 62 try { 63 commandLine = parser.parse(options, args); 64 } catch (ParseException ex) { 65 usage(); 66 return; 67 } 68 69 boolean disassemble = true; 70 boolean doDump = false; 71 boolean write = false; 72 boolean sort = false; 73 boolean fixRegisters = false; 74 boolean noParameterRegisters = false; 75 76 77 String outputDirectory = "out"; 78 String dumpFileName = null; 79 String outputDexFileName = null; 80 String inputDexFileName = null; 81 String deodexerantHost = null; 82 int deodexerantPort = 0; 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("n")) { 104 disassemble = false; 105 } 106 107 if (commandLine.hasOption("d")) { 108 doDump = true; 109 dumpFileName = commandLine.getOptionValue("d", inputDexFileName + ".dump"); 110 } 111 112 if (commandLine.hasOption("w")) { 113 write = true; 114 outputDexFileName = commandLine.getOptionValue("w"); 115 } 116 117 if (commandLine.hasOption("o")) { 118 outputDirectory = commandLine.getOptionValue("o"); 119 } 120 121 if (commandLine.hasOption("s")) { 122 sort = true; 123 } 124 125 if (commandLine.hasOption("f")) { 126 fixRegisters = true; 127 } 128 129 if (commandLine.hasOption("p")) { 130 noParameterRegisters = true; 131 } 132 133 if (commandLine.hasOption("x")) { 134 String deodexerantAddress = commandLine.getOptionValue("x"); 135 String[] parts = deodexerantAddress.split(":"); 136 if (parts.length != 2) { 137 System.err.println("Invalid deodexerant address. Expecting :<port> or <host>:<port>"); 138 System.exit(1); 139 } 140 141 deodexerantHost = parts[0]; 142 if (deodexerantHost.length() == 0) { 143 deodexerantHost = "localhost"; 144 } 145 try { 146 deodexerantPort = Integer.parseInt(parts[1]); 147 } catch (NumberFormatException ex) { 148 System.err.println("Invalid port \"" + deodexerantPort + "\" for deodexerant address"); 149 System.exit(1); 150 } 151 } 152 153 try { 154 File dexFileFile = new File(inputDexFileName); 155 if (!dexFileFile.exists()) { 156 System.err.println("Can't find the file " + inputDexFileName); 157 System.exit(1); 158 } 159 160 //Read in and parse the dex file 161 DexFile dexFile = new DexFile(dexFileFile, !fixRegisters); 162 163 Deodexerant deodexerant = null; 164 165 166 if (deodexerantHost != null) { 167 if (!dexFile.isOdex()) { 168 System.err.println("-x cannot be used with a normal dex file. Ignoring -x"); 169 } 170 deodexerant = new Deodexerant(dexFile, deodexerantHost, deodexerantPort); 171 } 172 173 if (dexFile.isOdex()) { 174 if (doDump) { 175 System.err.println("-d cannot be used with on odex file. Ignoring -d"); 176 } 177 if (write) { 178 System.err.println("-w cannot be used with an odex file. Ignoring -w"); 179 } 180 } 181 182 if (disassemble) { 183 baksmali.disassembleDexFile(dexFile, deodexerant, outputDirectory, noParameterRegisters); 184 } 185 186 if ((doDump || write) && !dexFile.isOdex()) { 187 try 188 { 189 dump.dump(dexFile, dumpFileName, outputDexFileName, sort); 190 }catch (IOException ex) { 191 System.err.println("Error occured while writing dump file"); 192 ex.printStackTrace(); 193 } 194 } 195 } catch (RuntimeException ex) { 196 System.err.println("\n\nUNEXPECTED TOP-LEVEL EXCEPTION:"); 197 ex.printStackTrace(); 198 System.exit(1); 199 } catch (Throwable ex) { 200 System.err.println("\n\nUNEXPECTED TOP-LEVEL ERROR:"); 201 ex.printStackTrace(); 202 System.exit(1); 203 } 204 } 205 206 /** 207 * Prints the usage message. 208 */ 209 private static void usage() { 210 HelpFormatter formatter = new HelpFormatter(); 211 formatter.printHelp("java -jar baksmali.jar [options] <dex-file>", 212 "disassembles and/or dumps a dex file", options, ""); 213 } 214 215 /** 216 * Prints the version message. 217 */ 218 private static void version() { 219 System.out.println("baksmali " + VERSION + " (http://smali.googlecode.com)"); 220 System.out.println("Copyright (C) 2009 Ben Gruver"); 221 System.out.println("BSD license (http://www.opensource.org/licenses/bsd-license.php)"); 222 System.exit(0); 223 } 224 225 private static void buildOptions() { 226 Option versionOption = OptionBuilder.withLongOpt("version") 227 .withDescription("prints the version then exits") 228 .create("v"); 229 230 Option helpOption = OptionBuilder.withLongOpt("help") 231 .withDescription("prints the help message then exits") 232 .create("?"); 233 234 Option noDisassemblyOption = OptionBuilder.withLongOpt("no-disassembly") 235 .withDescription("suppresses the output of the disassembly") 236 .create("n"); 237 238 Option dumpOption = OptionBuilder.withLongOpt("dump-to") 239 .withDescription("dumps the given dex file into a single annotated dump file named FILE" + 240 " (<dexfile>.dump by default), along with the normal disassembly.") 241 .hasOptionalArg() 242 .withArgName("FILE") 243 .create("d"); 244 245 Option writeDexOption = OptionBuilder.withLongOpt("write-dex") 246 .withDescription("additionally rewrites the input dex file to FILE") 247 .hasArg() 248 .withArgName("FILE") 249 .create("w"); 250 251 Option outputDirOption = OptionBuilder.withLongOpt("output") 252 .withDescription("the directory where the disassembled files will be placed. The default is out") 253 .hasArg() 254 .withArgName("DIR") 255 .create("o"); 256 257 Option sortOption = OptionBuilder.withLongOpt("sort") 258 .withDescription("sort the items in the dex file into a canonical order before dumping/writing") 259 .create("s"); 260 261 Option fixSignedRegisterOption = OptionBuilder.withLongOpt("fix-signed-registers") 262 .withDescription("when dumping or rewriting, fix any registers in the debug info that are encoded as" + 263 " a signed value") 264 .create("f"); 265 266 Option noParameterRegistersOption = OptionBuilder.withLongOpt("no-parameter-registers") 267 .withDescription("use the v<n> syntax instead of the p<n> syntax for registers mapped to method" + 268 " parameters") 269 .create("p"); 270 271 Option deodexerantOption = OptionBuilder.withLongOpt("deodexerant") 272 .withDescription("connect to deodexerant on the specified HOST:PORT, and deodex the input odex" 273 + " file. This option is ignored if the input file is a dex file instead of an odex file") 274 .hasArg() 275 .withArgName("HOST:PORT") 276 .create("x"); 277 278 OptionGroup dumpCommand = new OptionGroup(); 279 280 options.addOption(versionOption); 281 options.addOption(helpOption); 282 options.addOption(dumpOption); 283 options.addOption(noDisassemblyOption); 284 options.addOption(writeDexOption); 285 options.addOption(outputDirOption); 286 options.addOption(sortOption); 287 options.addOption(fixSignedRegisterOption); 288 options.addOption(noParameterRegistersOption); 289 options.addOption(deodexerantOption); 290 } 291}