main.java revision 4b171afedb983fb811990beeec6a15e30a90b455
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2a6260ff5696e3ae45f295463eaeada2cd75a8b85reed@android.com * [The "BSD licence"] 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright (c) 2010 Ben Gruver (JesusFreke) 4a6260ff5696e3ae45f295463eaeada2cd75a8b85reed@android.com * All rights reserved. 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Redistribution and use in source and binary forms, with or without 7a6260ff5696e3ae45f295463eaeada2cd75a8b85reed@android.com * modification, are permitted provided that the following conditions 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * are met: 9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 1. Redistributions of source code must retain the above copyright 1064a0ec36555352ec31aa7c5a7630a5d042b010badjsollen@google.com * notice, this list of conditions and the following disclaimer. 118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org * 2. Redistributions in binary form must reproduce the above copyright 128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org * notice, this list of conditions and the following disclaimer in the 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * documentation and/or other materials provided with the distribution. 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * 3. The name of the author may not be used to endorse or promote products 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * derived from this software without specific prior written permission. 162999f789c7e66a31066414f4b8fffb3148b677c5reed@google.com * 172999f789c7e66a31066414f4b8fffb3148b677c5reed@google.com * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 182999f789c7e66a31066414f4b8fffb3148b677c5reed@google.com * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 200a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a6260ff5696e3ae45f295463eaeada2cd75a8b85reed@android.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a6260ff5696e3ae45f295463eaeada2cd75a8b85reed@android.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compackage org.jf.baksmali; 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 310a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.comimport com.google.common.collect.Lists; 320a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.comimport org.apache.commons.cli.*; 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comimport org.jf.dexlib2.DexFileFactory; 3449f085dddff10473b6ebf832a974288300224e60bsalomonimport org.jf.dexlib2.analysis.CustomInlineMethodResolver; 350a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.comimport org.jf.dexlib2.dexbacked.DexBackedDexFile; 360a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.comimport org.jf.dexlib2.dexbacked.DexBackedOdexFile; 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comimport org.jf.util.ConsoleUtil; 380a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.comimport org.jf.util.SmaliHelpFormatter; 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 400a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.comimport javax.annotation.Nonnull; 41f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.comimport java.io.File; 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comimport java.io.IOException; 43a6260ff5696e3ae45f295463eaeada2cd75a8b85reed@android.comimport java.io.InputStream; 44a6260ff5696e3ae45f295463eaeada2cd75a8b85reed@android.comimport java.util.List; 45f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.comimport java.util.Locale; 460a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.comimport java.util.Properties; 47f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic class main { 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com public static final String VERSION; 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com private static final Options basicOptions; 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com private static final Options debugOptions; 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com private static final Options options; 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static { 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com options = new Options(); 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com basicOptions = new Options(); 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com debugOptions = new Options(); 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com buildOptions(); 610a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com InputStream templateStream = baksmali.class.getClassLoader().getResourceAsStream("baksmali.properties"); 63c9ab987efcb7e8b69237d565f73c28c137610232djsollen@google.com Properties properties = new Properties(); 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com String version = "(unknown)"; 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com try { 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com properties.load(templateStream); 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com version = properties.getProperty("application.version"); 680a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com } catch (IOException ex) { 690a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com // ignore 700a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com } 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com VERSION = version; 720a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com } 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** 750a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com * This class is uninstantiable. 760a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com */ 770a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com private main() { 780a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com } 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * Run! 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com public static void main(String[] args) throws IOException { 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Locale locale = new Locale("en", "US"); 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Locale.setDefault(locale); 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 878b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org CommandLineParser parser = new PosixParser(); 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CommandLine commandLine; 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com try { 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com commandLine = parser.parse(options, args); 920a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com } catch (ParseException ex) { 93c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com usage(); 94ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org return; 95ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org } 96ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org 97ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org baksmaliOptions options = new baksmaliOptions(); 98ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org 99ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org boolean disassemble = true; 100ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org boolean doDump = false; 101ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org String dumpFileName = null; 102ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org 10357313f6472684b14570562e43e84f5e2d6fcf278bsalomon@google.com String[] remainingArgs = commandLine.getArgs(); 104c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com 105025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org Option[] clOptions = commandLine.getOptions(); 10657313f6472684b14570562e43e84f5e2d6fcf278bsalomon@google.com 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i=0; i<clOptions.length; i++) { 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Option option = clOptions[i]; 1098b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org String opt = option.getOpt(); 1100a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com 111c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com switch (opt.charAt(0)) { 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case 'v': 113 version(); 114 return; 115 case '?': 116 while (++i < clOptions.length) { 117 if (clOptions[i].getOpt().charAt(0) == '?') { 118 usage(true); 119 return; 120 } 121 } 122 usage(false); 123 return; 124 case 'o': 125 options.outputDirectory = commandLine.getOptionValue("o"); 126 break; 127 case 'p': 128 options.noParameterRegisters = true; 129 break; 130 case 'l': 131 options.useLocalsDirective = true; 132 break; 133 case 's': 134 options.useSequentialLabels = true; 135 break; 136 case 'b': 137 options.outputDebugInfo = false; 138 break; 139 case 'd': 140 options.bootClassPathDirs.add(option.getValue()); 141 break; 142 case 'f': 143 options.addCodeOffsets = true; 144 break; 145 case 'r': 146 String[] values = commandLine.getOptionValues('r'); 147 int registerInfo = 0; 148 149 if (values == null || values.length == 0) { 150 registerInfo = baksmaliOptions.ARGS | baksmaliOptions.DEST; 151 } else { 152 for (String value: values) { 153 if (value.equalsIgnoreCase("ALL")) { 154 registerInfo |= baksmaliOptions.ALL; 155 } else if (value.equalsIgnoreCase("ALLPRE")) { 156 registerInfo |= baksmaliOptions.ALLPRE; 157 } else if (value.equalsIgnoreCase("ALLPOST")) { 158 registerInfo |= baksmaliOptions.ALLPOST; 159 } else if (value.equalsIgnoreCase("ARGS")) { 160 registerInfo |= baksmaliOptions.ARGS; 161 } else if (value.equalsIgnoreCase("DEST")) { 162 registerInfo |= baksmaliOptions.DEST; 163 } else if (value.equalsIgnoreCase("MERGE")) { 164 registerInfo |= baksmaliOptions.MERGE; 165 } else if (value.equalsIgnoreCase("FULLMERGE")) { 166 registerInfo |= baksmaliOptions.FULLMERGE; 167 } else { 168 usage(); 169 return; 170 } 171 } 172 173 if ((registerInfo & baksmaliOptions.FULLMERGE) != 0) { 174 registerInfo &= ~baksmaliOptions.MERGE; 175 } 176 } 177 options.registerInfo = registerInfo; 178 break; 179 case 'c': 180 String bcp = commandLine.getOptionValue("c"); 181 if (bcp != null && bcp.charAt(0) == ':') { 182 options.addExtraClassPath(bcp); 183 } else { 184 options.setBootClassPath(bcp); 185 } 186 break; 187 case 'x': 188 options.deodex = true; 189 break; 190 case 'm': 191 options.noAccessorComments = true; 192 break; 193 case 'a': 194 options.apiLevel = Integer.parseInt(commandLine.getOptionValue("a")); 195 break; 196 case 'N': 197 disassemble = false; 198 break; 199 case 'D': 200 doDump = true; 201 dumpFileName = commandLine.getOptionValue("D"); 202 break; 203 case 'I': 204 options.ignoreErrors = true; 205 break; 206 case 'T': 207 options.inlineResolver = new CustomInlineMethodResolver(options.classPath, new File(commandLine.getOptionValue("T"))); 208 break; 209 case 'K': 210 options.checkPackagePrivateAccess = true; 211 break; 212 default: 213 assert false; 214 } 215 } 216 217 if (remainingArgs.length != 1) { 218 usage(); 219 return; 220 } 221 222 String inputDexFileName = remainingArgs[0]; 223 224 File dexFileFile = new File(inputDexFileName); 225 if (!dexFileFile.exists()) { 226 System.err.println("Can't find the file " + inputDexFileName); 227 System.exit(1); 228 } 229 230 //Read in and parse the dex file 231 DexBackedDexFile dexFile = DexFileFactory.loadDexFile(dexFileFile, options.apiLevel); 232 233 if (dexFile.isOdexFile()) { 234 if (!options.deodex) { 235 System.err.println("Warning: You are disassembling an odex file without deodexing it. You"); 236 System.err.println("won't be able to re-assemble the results unless you deodex it with the -x"); 237 System.err.println("option"); 238 } 239 } else { 240 options.deodex = false; 241 } 242 243 244 if ((options.deodex || options.registerInfo != 0) && options.bootClassPathEntries == null) { 245 if (dexFile instanceof DexBackedOdexFile) { 246 ((DexBackedOdexFile)dexFile).getDependencies(); 247 } else { 248 options.bootClassPathEntries = getDefaultBootClassPathForApi(options.apiLevel); 249 } 250 } 251 252 if (disassemble) { 253 baksmali.disassembleDexFile(dexFile, options); 254 } 255 256 if (doDump) { 257 if (dumpFileName == null) { 258 dumpFileName = commandLine.getOptionValue(inputDexFileName + ".dump"); 259 } 260 dump.dump(dexFile, dumpFileName, options.apiLevel); 261 } 262 } 263 264 /** 265 * Prints the usage message. 266 */ 267 private static void usage(boolean printDebugOptions) { 268 SmaliHelpFormatter formatter = new SmaliHelpFormatter(); 269 int consoleWidth = ConsoleUtil.getConsoleWidth(); 270 if (consoleWidth <= 0) { 271 consoleWidth = 80; 272 } 273 274 formatter.setWidth(consoleWidth); 275 276 formatter.printHelp("java -jar baksmali.jar [options] <dex-file>", 277 "disassembles and/or dumps a dex file", basicOptions, printDebugOptions?debugOptions:null); 278 } 279 280 private static void usage() { 281 usage(false); 282 } 283 284 /** 285 * Prints the version message. 286 */ 287 protected static void version() { 288 System.out.println("baksmali " + VERSION + " (http://smali.googlecode.com)"); 289 System.out.println("Copyright (C) 2010 Ben Gruver (JesusFreke@JesusFreke.com)"); 290 System.out.println("BSD license (http://www.opensource.org/licenses/bsd-license.php)"); 291 System.exit(0); 292 } 293 294 @SuppressWarnings("AccessStaticViaInstance") 295 private static void buildOptions() { 296 Option versionOption = OptionBuilder.withLongOpt("version") 297 .withDescription("prints the version then exits") 298 .create("v"); 299 300 Option helpOption = OptionBuilder.withLongOpt("help") 301 .withDescription("prints the help message then exits. Specify twice for debug options") 302 .create("?"); 303 304 Option outputDirOption = OptionBuilder.withLongOpt("output") 305 .withDescription("the directory where the disassembled files will be placed. The default is out") 306 .hasArg() 307 .withArgName("DIR") 308 .create("o"); 309 310 Option noParameterRegistersOption = OptionBuilder.withLongOpt("no-parameter-registers") 311 .withDescription("use the v<n> syntax instead of the p<n> syntax for registers mapped to method " + 312 "parameters") 313 .create("p"); 314 315 Option deodexerantOption = OptionBuilder.withLongOpt("deodex") 316 .withDescription("deodex the given odex file. This option is ignored if the input file is not an " + 317 "odex file") 318 .create("x"); 319 320 Option useLocalsOption = OptionBuilder.withLongOpt("use-locals") 321 .withDescription("output the .locals directive with the number of non-parameter registers, rather" + 322 " than the .register directive with the total number of register") 323 .create("l"); 324 325 Option sequentialLabelsOption = OptionBuilder.withLongOpt("sequential-labels") 326 .withDescription("create label names using a sequential numbering scheme per label type, rather than " + 327 "using the bytecode address") 328 .create("s"); 329 330 Option noDebugInfoOption = OptionBuilder.withLongOpt("no-debug-info") 331 .withDescription("don't write out debug info (.local, .param, .line, etc.)") 332 .create("b"); 333 334 Option registerInfoOption = OptionBuilder.withLongOpt("register-info") 335 .hasOptionalArgs() 336 .withArgName("REGISTER_INFO_TYPES") 337 .withValueSeparator(',') 338 .withDescription("print the specificed type(s) of register information for each instruction. " + 339 "\"ARGS,DEST\" is the default if no types are specified.\nValid values are:\nALL: all " + 340 "pre- and post-instruction registers.\nALLPRE: all pre-instruction registers\nALLPOST: all " + 341 "post-instruction registers\nARGS: any pre-instruction registers used as arguments to the " + 342 "instruction\nDEST: the post-instruction destination register, if any\nMERGE: Any " + 343 "pre-instruction register has been merged from more than 1 different post-instruction " + 344 "register from its predecessors\nFULLMERGE: For each register that would be printed by " + 345 "MERGE, also show the incoming register types that were merged") 346 .create("r"); 347 348 Option classPathOption = OptionBuilder.withLongOpt("bootclasspath") 349 .withDescription("the bootclasspath jars to use, for analysis. Defaults to " + 350 "core.jar:ext.jar:framework.jar:android.policy.jar:services.jar. If the value begins with a " + 351 ":, it will be appended to the default bootclasspath instead of replacing it") 352 .hasOptionalArg() 353 .withArgName("BOOTCLASSPATH") 354 .create("c"); 355 356 Option classPathDirOption = OptionBuilder.withLongOpt("bootclasspath-dir") 357 .withDescription("the base folder to look for the bootclasspath files in. Defaults to the current " + 358 "directory") 359 .hasArg() 360 .withArgName("DIR") 361 .create("d"); 362 363 Option codeOffsetOption = OptionBuilder.withLongOpt("code-offsets") 364 .withDescription("add comments to the disassembly containing the code offset for each address") 365 .create("f"); 366 367 Option noAccessorCommentsOption = OptionBuilder.withLongOpt("no-accessor-comments") 368 .withDescription("don't output helper comments for synthetic accessors") 369 .create("m"); 370 371 Option apiLevelOption = OptionBuilder.withLongOpt("api-level") 372 .withDescription("The numeric api-level of the file being disassembled. If not " + 373 "specified, it defaults to 15 (ICS).") 374 .hasArg() 375 .withArgName("API_LEVEL") 376 .create("a"); 377 378 Option dumpOption = OptionBuilder.withLongOpt("dump-to") 379 .withDescription("dumps the given dex file into a single annotated dump file named FILE" + 380 " (<dexfile>.dump by default), along with the normal disassembly") 381 .hasOptionalArg() 382 .withArgName("FILE") 383 .create("D"); 384 385 Option ignoreErrorsOption = OptionBuilder.withLongOpt("ignore-errors") 386 .withDescription("ignores any non-fatal errors that occur while disassembling/deodexing," + 387 " ignoring the class if needed, and continuing with the next class. The default" + 388 " behavior is to stop disassembling and exit once an error is encountered") 389 .create("I"); 390 391 Option noDisassemblyOption = OptionBuilder.withLongOpt("no-disassembly") 392 .withDescription("suppresses the output of the disassembly") 393 .create("N"); 394 395 Option inlineTableOption = OptionBuilder.withLongOpt("inline-table") 396 .withDescription("specify a file containing a custom inline method table to use for deodexing") 397 .hasArg() 398 .withArgName("FILE") 399 .create("T"); 400 401 Option checkPackagePrivateAccess = OptionBuilder.withLongOpt("check-package-private-access") 402 .withDescription("When deodexing, use the new virtual table generation logic that " + 403 "prevents overriding an inaccessible package private method. This is a temporary option " + 404 "that will be removed once this new functionality can be tied to a specific api level.") 405 .create("K"); 406 407 basicOptions.addOption(versionOption); 408 basicOptions.addOption(helpOption); 409 basicOptions.addOption(outputDirOption); 410 basicOptions.addOption(noParameterRegistersOption); 411 basicOptions.addOption(deodexerantOption); 412 basicOptions.addOption(useLocalsOption); 413 basicOptions.addOption(sequentialLabelsOption); 414 basicOptions.addOption(noDebugInfoOption); 415 basicOptions.addOption(registerInfoOption); 416 basicOptions.addOption(classPathOption); 417 basicOptions.addOption(classPathDirOption); 418 basicOptions.addOption(codeOffsetOption); 419 basicOptions.addOption(noAccessorCommentsOption); 420 basicOptions.addOption(apiLevelOption); 421 422 debugOptions.addOption(dumpOption); 423 debugOptions.addOption(ignoreErrorsOption); 424 debugOptions.addOption(noDisassemblyOption); 425 debugOptions.addOption(inlineTableOption); 426 debugOptions.addOption(checkPackagePrivateAccess); 427 428 for (Object option: basicOptions.getOptions()) { 429 options.addOption((Option)option); 430 } 431 for (Object option: debugOptions.getOptions()) { 432 options.addOption((Option)option); 433 } 434 } 435 436 @Nonnull 437 private static List<String> getDefaultBootClassPathForApi(int apiLevel) { 438 if (apiLevel < 9) { 439 return Lists.newArrayList( 440 "/system/framework/core.jar", 441 "/system/framework/ext.jar", 442 "/system/framework/framework.jar", 443 "/system/framework/android.policy.jar", 444 "/system/framework/services.jar"); 445 } else if (apiLevel < 12) { 446 return Lists.newArrayList( 447 "/system/framework/core.jar", 448 "/system/framework/bouncycastle.jar", 449 "/system/framework/ext.jar", 450 "/system/framework/framework.jar", 451 "/system/framework/android.policy.jar", 452 "/system/framework/services.jar", 453 "/system/framework/core-junit.jar"); 454 } else if (apiLevel < 14) { 455 return Lists.newArrayList( 456 "/system/framework/core.jar", 457 "/system/framework/apache-xml.jar", 458 "/system/framework/bouncycastle.jar", 459 "/system/framework/ext.jar", 460 "/system/framework/framework.jar", 461 "/system/framework/android.policy.jar", 462 "/system/framework/services.jar", 463 "/system/framework/core-junit.jar"); 464 } else if (apiLevel < 16) { 465 return Lists.newArrayList( 466 "/system/framework/core.jar", 467 "/system/framework/core-junit.jar", 468 "/system/framework/bouncycastle.jar", 469 "/system/framework/ext.jar", 470 "/system/framework/framework.jar", 471 "/system/framework/android.policy.jar", 472 "/system/framework/services.jar", 473 "/system/framework/apache-xml.jar", 474 "/system/framework/filterfw.jar"); 475 476 } else { 477 // this is correct as of api 17/4.2.2 478 return Lists.newArrayList( 479 "/system/framework/core.jar", 480 "/system/framework/core-junit.jar", 481 "/system/framework/bouncycastle.jar", 482 "/system/framework/ext.jar", 483 "/system/framework/framework.jar", 484 "/system/framework/telephony-common.jar", 485 "/system/framework/mms-common.jar", 486 "/system/framework/android.policy.jar", 487 "/system/framework/services.jar", 488 "/system/framework/apache-xml.jar"); 489 } 490 } 491}