main.java revision fbea4e751fa6f1748ded4379a4b64601cb53ba7b
158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/* 258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * [The "BSD licence"] 358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * Copyright (c) 2010 Ben Gruver (JesusFreke) 458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * All rights reserved. 558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * 658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * modification, are permitted provided that the following conditions 858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * are met: 958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright 1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright 1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * notice, this list of conditions and the following disclaimer in the 1358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * documentation and/or other materials provided with the distribution. 1458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * 3. The name of the author may not be used to endorse or promote products 1558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * derived from this software without specific prior written permission. 1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * 1758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) */ 2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)package org.jf.baksmali; 3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 3158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)import org.apache.commons.cli.*; 3258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)import org.jf.dexlib.DexFile; 3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)import org.jf.util.ConsoleUtil; 3458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)import org.jf.util.smaliHelpFormatter; 3558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 3658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)import java.io.File; 3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)import java.io.IOException; 3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)import java.io.InputStream; 3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)import java.util.ArrayList; 4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)import java.util.List; 4158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)import java.util.Properties; 4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)public class main { 4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public static final String VERSION; 4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) private static final Options basicOptions; 4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) private static final Options debugOptions; 4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) private static final Options options; 5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public static final int ALL = 1; 5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public static final int ALLPRE = 2; 5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public static final int ALLPOST = 4; 5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public static final int ARGS = 8; 5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public static final int DEST = 16; 5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public static final int MERGE = 32; 5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public static final int FULLMERGE = 64; 5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) static { 6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) options = new Options(); 6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) basicOptions = new Options(); 6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) debugOptions = new Options(); 6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) buildOptions(); 6458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) InputStream templateStream = baksmali.class.getClassLoader().getResourceAsStream("baksmali.properties"); 6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Properties properties = new Properties(); 6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) String version = "(unknown)"; 6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) try { 6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) properties.load(templateStream); 7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) version = properties.getProperty("application.version"); 7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } catch (IOException ex) { 7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) VERSION = version; 7458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) /** 7758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * This class is uninstantiable. 7858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) */ 7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) private main() { 8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) /** 8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * Run! 8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) */ 8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public static void main(String[] args) { 8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CommandLineParser parser = new PosixParser(); 8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CommandLine commandLine; 8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) try { 9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) commandLine = parser.parse(options, args); 9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } catch (ParseException ex) { 9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) usage(); 9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) boolean disassemble = true; 9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) boolean doDump = false; 9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) boolean write = false; 9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) boolean sort = false; 10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) boolean fixRegisters = false; 10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) boolean noParameterRegisters = false; 10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) boolean useLocalsDirective = false; 10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) boolean useSequentialLabels = false; 10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) boolean outputDebugInfo = true; 10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) boolean addCodeOffsets = false; 10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) boolean deodex = false; 10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) boolean verify = false; 10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) boolean ignoreErrors = false; 10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int registerInfo = 0; 11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) String outputDirectory = "out"; 11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) String dumpFileName = null; 11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) String outputDexFileName = null; 11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) String inputDexFileName = null; 11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) String bootClassPath = null; 11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) StringBuffer extraBootClassPathEntries = new StringBuffer(); 11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) List<String> bootClassPathDirs = new ArrayList<String>(); 11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bootClassPathDirs.add("."); 12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) String[] remainingArgs = commandLine.getArgs(); 12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Option[] options = commandLine.getOptions(); 12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) for (int i=0; i<options.length; i++) { 12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Option option = options[i]; 12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) String opt = option.getOpt(); 12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) switch (opt.charAt(0)) { 13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case 'v': 13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) version(); 13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case '?': 13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) while (++i < options.length) { 13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (options[i].getOpt().charAt(0) == '?') { 13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) usage(true); 13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) usage(false); 14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 14358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case 'o': 14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) outputDirectory = commandLine.getOptionValue("o"); 14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case 'p': 14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) noParameterRegisters = true; 14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) break; 14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) case 'l': 15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) useLocalsDirective = true; 151 break; 152 case 's': 153 useSequentialLabels = true; 154 break; 155 case 'b': 156 outputDebugInfo = false; 157 break; 158 case 'd': 159 bootClassPathDirs.add(option.getValue()); 160 break; 161 case 'f': 162 addCodeOffsets = true; 163 break; 164 case 'r': 165 String[] values = commandLine.getOptionValues('r'); 166 167 if (values == null || values.length == 0) { 168 registerInfo = ARGS | DEST; 169 } else { 170 for (String value: values) { 171 if (value.equalsIgnoreCase("ALL")) { 172 registerInfo |= ALL; 173 } else if (value.equalsIgnoreCase("ALLPRE")) { 174 registerInfo |= ALLPRE; 175 } else if (value.equalsIgnoreCase("ALLPOST")) { 176 registerInfo |= ALLPOST; 177 } else if (value.equalsIgnoreCase("ARGS")) { 178 registerInfo |= ARGS; 179 } else if (value.equalsIgnoreCase("DEST")) { 180 registerInfo |= DEST; 181 } else if (value.equalsIgnoreCase("MERGE")) { 182 registerInfo |= MERGE; 183 } else if (value.equalsIgnoreCase("FULLMERGE")) { 184 registerInfo |= FULLMERGE; 185 } else { 186 usage(); 187 return; 188 } 189 } 190 191 if ((registerInfo & FULLMERGE) != 0) { 192 registerInfo &= ~MERGE; 193 } 194 } 195 break; 196 case 'c': 197 String bcp = commandLine.getOptionValue("c"); 198 if (bcp != null && bcp.charAt(0) == ':') { 199 extraBootClassPathEntries.append(bcp); 200 } else { 201 bootClassPath = bcp; 202 } 203 break; 204 case 'x': 205 deodex = true; 206 break; 207 case 'N': 208 disassemble = false; 209 break; 210 case 'D': 211 doDump = true; 212 dumpFileName = commandLine.getOptionValue("D", inputDexFileName + ".dump"); 213 break; 214 case 'I': 215 ignoreErrors = true; 216 break; 217 case 'W': 218 write = true; 219 outputDexFileName = commandLine.getOptionValue("W"); 220 break; 221 case 'S': 222 sort = true; 223 break; 224 case 'F': 225 fixRegisters = true; 226 break; 227 case 'V': 228 verify = true; 229 break; 230 default: 231 assert false; 232 } 233 } 234 235 if (remainingArgs.length != 1) { 236 usage(); 237 return; 238 } 239 240 inputDexFileName = remainingArgs[0]; 241 242 try { 243 File dexFileFile = new File(inputDexFileName); 244 if (!dexFileFile.exists()) { 245 System.err.println("Can't find the file " + inputDexFileName); 246 System.exit(1); 247 } 248 249 //Read in and parse the dex file 250 DexFile dexFile = new DexFile(dexFileFile, !fixRegisters, false); 251 252 if (dexFile.isOdex()) { 253 if (doDump) { 254 System.err.println("-D cannot be used with on odex file. Ignoring -D"); 255 } 256 if (write) { 257 System.err.println("-W cannot be used with an odex file. Ignoring -W"); 258 } 259 if (!deodex) { 260 System.err.println("Warning: You are disassembling an odex file without deodexing it. You"); 261 System.err.println("won't be able to re-assemble the results unless you deodex it with the -x"); 262 System.err.println("option"); 263 } 264 } else { 265 deodex = false; 266 267 if (bootClassPath == null) { 268 bootClassPath = "core.jar:ext.jar:framework.jar:android.policy.jar:services.jar"; 269 } 270 } 271 272 if (disassemble) { 273 String[] bootClassPathDirsArray = new String[bootClassPathDirs.size()]; 274 for (int i=0; i<bootClassPathDirsArray.length; i++) { 275 bootClassPathDirsArray[i] = bootClassPathDirs.get(i); 276 } 277 278 baksmali.disassembleDexFile(dexFileFile.getPath(), dexFile, deodex, outputDirectory, 279 bootClassPathDirsArray, bootClassPath, extraBootClassPathEntries.toString(), 280 noParameterRegisters, useLocalsDirective, useSequentialLabels, outputDebugInfo, addCodeOffsets, 281 registerInfo, verify, ignoreErrors); 282 } 283 284 if ((doDump || write) && !dexFile.isOdex()) { 285 try 286 { 287 dump.dump(dexFile, dumpFileName, outputDexFileName, sort); 288 }catch (IOException ex) { 289 System.err.println("Error occured while writing dump file"); 290 ex.printStackTrace(); 291 } 292 } 293 } catch (RuntimeException ex) { 294 System.err.println("\n\nUNEXPECTED TOP-LEVEL EXCEPTION:"); 295 ex.printStackTrace(); 296 System.exit(1); 297 } catch (Throwable ex) { 298 System.err.println("\n\nUNEXPECTED TOP-LEVEL ERROR:"); 299 ex.printStackTrace(); 300 System.exit(1); 301 } 302 } 303 304 /** 305 * Prints the usage message. 306 */ 307 private static void usage(boolean printDebugOptions) { 308 smaliHelpFormatter formatter = new smaliHelpFormatter(); 309 formatter.setWidth(ConsoleUtil.getConsoleWidth()); 310 311 formatter.printHelp("java -jar baksmali.jar [options] <dex-file>", 312 "disassembles and/or dumps a dex file", basicOptions, ""); 313 314 if (printDebugOptions) { 315 System.out.println(); 316 System.out.println("Debug Options:"); 317 318 StringBuffer sb = new StringBuffer(); 319 formatter.renderOptions(sb, debugOptions); 320 System.out.println(sb.toString()); 321 } 322 } 323 324 private static void usage() { 325 usage(false); 326 } 327 328 /** 329 * Prints the version message. 330 */ 331 protected static void version() { 332 System.out.println("baksmali " + VERSION + " (http://smali.googlecode.com)"); 333 System.out.println("Copyright (C) 2010 Ben Gruver (JesusFreke@JesusFreke.com)"); 334 System.out.println("BSD license (http://www.opensource.org/licenses/bsd-license.php)"); 335 System.exit(0); 336 } 337 338 private static void buildOptions() { 339 Option versionOption = OptionBuilder.withLongOpt("version") 340 .withDescription("prints the version then exits") 341 .create("v"); 342 343 Option helpOption = OptionBuilder.withLongOpt("help") 344 .withDescription("prints the help message then exits. Specify twice for debug options") 345 .create("?"); 346 347 Option outputDirOption = OptionBuilder.withLongOpt("output") 348 .withDescription("the directory where the disassembled files will be placed. The default is out") 349 .hasArg() 350 .withArgName("DIR") 351 .create("o"); 352 353 Option noParameterRegistersOption = OptionBuilder.withLongOpt("no-parameter-registers") 354 .withDescription("use the v<n> syntax instead of the p<n> syntax for registers mapped to method " + 355 "parameters") 356 .create("p"); 357 358 Option deodexerantOption = OptionBuilder.withLongOpt("deodex") 359 .withDescription("deodex the given odex file. This option is ignored if the input file is not an " + 360 "odex file") 361 .create("x"); 362 363 Option useLocalsOption = OptionBuilder.withLongOpt("use-locals") 364 .withDescription("output the .locals directive with the number of non-parameter registers, rather" + 365 " than the .register directive with the total number of register") 366 .create("l"); 367 368 Option sequentialLabelsOption = OptionBuilder.withLongOpt("sequential-labels") 369 .withDescription("create label names using a sequential numbering scheme per label type, rather than " + 370 "using the bytecode address") 371 .create("s"); 372 373 Option noDebugInfoOption = OptionBuilder.withLongOpt("no-debug-info") 374 .withDescription("don't write out debug info (.local, .param, .line, etc.)") 375 .create("b"); 376 377 Option registerInfoOption = OptionBuilder.withLongOpt("register-info") 378 .hasOptionalArgs() 379 .withArgName("REGISTER_INFO_TYPES") 380 .withValueSeparator(',') 381 .withDescription("print the specificed type(s) of register information for each instruction. " + 382 "\"ARGS,DEST\" is the default if no types are specified.\nValid values are:\nALL: all " + 383 "pre- and post-instruction registers.\nALLPRE: all pre-instruction registers\nALLPOST: all " + 384 "post-instruction registers\nARGS: any pre-instruction registers used as arguments to the " + 385 "instruction\nDEST: the post-instruction destination register, if any\nMERGE: Any " + 386 "pre-instruction register has been merged from more than 1 different post-instruction " + 387 "register from its predecessors\nFULLMERGE: For each register that would be printed by " + 388 "MERGE, also show the incoming register types that were merged") 389 .create("r"); 390 391 Option classPathOption = OptionBuilder.withLongOpt("bootclasspath") 392 .withDescription("the bootclasspath jars to use, for analysis. Defaults to " + 393 "core.jar:ext.jar:framework.jar:android.policy.jar:services.jar. If the value begins with a " + 394 ":, it will be appended to the default bootclasspath instead of replacing it") 395 .hasOptionalArg() 396 .withArgName("BOOTCLASSPATH") 397 .create("c"); 398 399 Option classPathDirOption = OptionBuilder.withLongOpt("bootclasspath-dir") 400 .withDescription("the base folder to look for the bootclasspath files in. Defaults to the current " + 401 "directory") 402 .hasArg() 403 .withArgName("DIR") 404 .create("d"); 405 406 Option codeOffsetOption = OptionBuilder.withLongOpt("code-offsets") 407 .withDescription("add comments to the disassembly containing the code offset for each address") 408 .create("f"); 409 410 411 412 Option dumpOption = OptionBuilder.withLongOpt("dump-to") 413 .withDescription("dumps the given dex file into a single annotated dump file named FILE" + 414 " (<dexfile>.dump by default), along with the normal disassembly") 415 .hasOptionalArg() 416 .withArgName("FILE") 417 .create("D"); 418 419 Option ignoreErrorsOption = OptionBuilder.withLongOpt("ignore-errors") 420 .withDescription("ignores any non-fatal errors that occur while disassembling/deodexing," + 421 " ignoring the class if needed, and continuing with the next class. The default" + 422 " behavior is to stop disassembling and exit once an error is encountered") 423 .create("I"); 424 425 Option noDisassemblyOption = OptionBuilder.withLongOpt("no-disassembly") 426 .withDescription("suppresses the output of the disassembly") 427 .create("N"); 428 429 Option writeDexOption = OptionBuilder.withLongOpt("write-dex") 430 .withDescription("additionally rewrites the input dex file to FILE") 431 .hasArg() 432 .withArgName("FILE") 433 .create("W"); 434 435 Option sortOption = OptionBuilder.withLongOpt("sort") 436 .withDescription("sort the items in the dex file into a canonical order before dumping/writing") 437 .create("S"); 438 439 Option fixSignedRegisterOption = OptionBuilder.withLongOpt("fix-signed-registers") 440 .withDescription("when dumping or rewriting, fix any registers in the debug info that are encoded as" + 441 " a signed value") 442 .create("F"); 443 444 Option verifyDexOption = OptionBuilder.withLongOpt("verify") 445 .withDescription("perform bytecode verification") 446 .create("V"); 447 448 basicOptions.addOption(versionOption); 449 basicOptions.addOption(helpOption); 450 basicOptions.addOption(outputDirOption); 451 basicOptions.addOption(noParameterRegistersOption); 452 basicOptions.addOption(deodexerantOption); 453 basicOptions.addOption(useLocalsOption); 454 basicOptions.addOption(sequentialLabelsOption); 455 basicOptions.addOption(noDebugInfoOption); 456 basicOptions.addOption(registerInfoOption); 457 basicOptions.addOption(classPathOption); 458 basicOptions.addOption(classPathDirOption); 459 basicOptions.addOption(codeOffsetOption); 460 461 debugOptions.addOption(dumpOption); 462 debugOptions.addOption(ignoreErrorsOption); 463 debugOptions.addOption(noDisassemblyOption); 464 debugOptions.addOption(writeDexOption); 465 debugOptions.addOption(sortOption); 466 debugOptions.addOption(fixSignedRegisterOption); 467 debugOptions.addOption(verifyDexOption); 468 469 470 for (Object option: basicOptions.getOptions()) { 471 options.addOption((Option)option); 472 } 473 for (Object option: debugOptions.getOptions()) { 474 options.addOption((Option)option); 475 } 476 } 477}