1959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle/* 2959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Copyright (C) 2014 The Android Open Source Project 3959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * 4959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Licensed under the Apache License, Version 2.0 (the "License"); 5959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * you may not use this file except in compliance with the License. 6959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * You may obtain a copy of the License at 7959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * 8959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * http://www.apache.org/licenses/LICENSE-2.0 9959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * 10959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Unless required by applicable law or agreed to in writing, software 11959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * distributed under the License is distributed on an "AS IS" BASIS, 12959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * See the License for the specific language governing permissions and 14959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * limitations under the License. 15959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 16959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 17959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepackage dexfuzz; 18959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 19959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.Log.LogTag; 20959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 21959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.io.BufferedReader; 22959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.io.File; 23959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.io.FileNotFoundException; 24959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.io.FileReader; 25959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.io.IOException; 26959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.ArrayList; 27959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.HashMap; 28959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.List; 29959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.Map; 30959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 31959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle/** 32959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Stores options for dexfuzz. 33959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 34959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepublic class Options { 35959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 36959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Constructor has been disabled for this class, which should only be used statically. 37959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 38959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private Options() { } 39959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 40959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // KEY VALUE OPTIONS 41959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static final List<String> inputFileList = new ArrayList<String>(); 42959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static String outputFile = ""; 43959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static long rngSeed = -1; 44959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean usingProvidedSeed = false; 45959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static int methodMutations = 3; 46959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static int minMethods = 2; 47959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static int maxMethods = 10; 48959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static final Map<String,Integer> mutationLikelihoods = new HashMap<String,Integer>(); 49959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static String executeClass = "Main"; 50959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static String deviceName = ""; 51959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean usingSpecificDevice = false; 52959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static int repeat = 1; 53959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static String executeDirectory = "/data/art-test"; 54959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static String dumpMutationsFile = "mutations.dump"; 55959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static String loadMutationsFile = "mutations.dump"; 56959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static String reportLogFile = "report.log"; 57959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static String uniqueDatabaseFile = "unique_progs.db"; 58959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 59959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // FLAG OPTIONS 60959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean execute; 61807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle public static boolean executeOnHost; 62959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean noBootImage; 63959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean useInterpreter; 64959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean useQuick; 65959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean useOptimizing; 66959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean useArchArm; 67959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean useArchArm64; 68959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean useArchX86; 69959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean useArchX86_64; 70959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean useArchMips; 71959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean useArchMips64; 72959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean skipHostVerify; 73959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean shortTimeouts; 74959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean dumpOutput; 75959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean dumpVerify; 76959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean mutateLimit; 77959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean reportUnique; 78959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean skipMutation; 79959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean dumpMutations; 80959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean loadMutations; 81959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 82959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 83959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Print out usage information about dexfuzz, and then exit. 84959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 85959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static void usage() { 86959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always("DexFuzz Usage:"); 87959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --input=<file> : Seed DEX file to be fuzzed"); 88959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" (Can specify multiple times.)"); 89959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --inputs=<file> : Directory containing DEX files to be fuzzed."); 90959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --output=<file> : Output DEX file to be produced"); 91959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(""); 92959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --execute : Execute the resulting fuzzed program"); 93807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle Log.always(" --host : Execute on host"); 94959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --device=<device> : Execute on an ADB-connected-device, where <device> is"); 95959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" the argument given to adb -s. Default execution mode."); 96959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --execute-dir=<dir> : Push tests to this directory to execute them."); 97959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" (Default: /data/art-test)"); 98959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --no-boot-image : Use this flag when boot.art is not available."); 99959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --skip-host-verify : When executing, skip host-verification stage"); 100959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --execute-class=<c> : When executing, execute this class (default: Main)"); 101959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(""); 102959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --interpreter : Include the Interpreter in comparisons"); 103959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --quick : Include the Quick Compiler in comparisons"); 104959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --optimizing : Include the Optimizing Compiler in comparisons"); 105959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(""); 106959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --arm : Include ARM backends in comparisons"); 107959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --arm64 : Include ARM64 backends in comparisons"); 108959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --allarm : Short for --arm --arm64"); 109959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --x86 : Include x86 backends in comparisons"); 110959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --x86-64 : Include x86-64 backends in comparisons"); 111959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --mips : Include MIPS backends in comparisons"); 112959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --mips64 : Include MIPS64 backends in comparisons"); 113959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(""); 114959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --dump-output : Dump outputs of executed programs"); 115959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --dump-verify : Dump outputs of verification"); 116959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --repeat=<n> : Fuzz N programs, executing each one."); 117959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --short-timeouts : Shorten timeouts (faster; use if"); 118959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" you want to focus on output divergences)"); 119959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --seed=<seed> : RNG seed to use"); 120959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --method-mutations=<n> : Maximum number of mutations to perform on each method."); 121959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" (Default: 3)"); 122959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --min-methods=<n> : Minimum number of methods to mutate. (Default: 2)"); 123959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --max-methods=<n> : Maximum number of methods to mutate. (Default: 10)"); 124959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --one-mutation : Short for --method-mutations=1 "); 125959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --min-methods=1 --max-methods=1"); 126959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --likelihoods=<file> : A file containing a table of mutation likelihoods"); 127959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --mutate-limit : Mutate only methods whose names end with _MUTATE"); 128959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --skip-mutation : Do not actually mutate the input, just output it"); 129959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" after parsing"); 130959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(""); 131959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --dump-mutations[=<file>] : Dump an editable set of mutations applied"); 132959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" to <file> (default: mutations.dump)"); 133959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --load-mutations[=<file>] : Load and apply a set of mutations"); 134959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" from <file> (default: mutations.dump)"); 135959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --log=<tag> : Set more verbose logging level: DEBUG, INFO, WARN"); 136959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --report=<file> : Use <file> to report results when using --repeat"); 137959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" (Default: report.log)"); 138959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --report-unique : Print out information about unique programs generated"); 139959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" --unique-db=<file> : Use <file> store results about unique programs"); 140959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(" (Default: unique_progs.db)"); 141959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always(""); 142959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle System.exit(0); 143959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 144959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 145959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 146959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Given a flag option (one that does not feature an =), handle it 147959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * accordingly. Report an error and print usage info if the flag is not 148959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * recognised. 149959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 150959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private static void handleFlagOption(String flag) { 151959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (flag.equals("execute")) { 152959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle execute = true; 153807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle } else if (flag.equals("host")) { 154807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle executeOnHost = true; 155959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("no-boot-image")) { 156959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle noBootImage = true; 157959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("skip-host-verify")) { 158959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle skipHostVerify = true; 159959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("interpreter")) { 160959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle useInterpreter = true; 161959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("quick")) { 162959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle useQuick = true; 163959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("optimizing")) { 164959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle useOptimizing = true; 165959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("arm")) { 166959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle useArchArm = true; 167959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("arm64")) { 168959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle useArchArm64 = true; 169959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("allarm")) { 170959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle useArchArm = true; 171959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle useArchArm64 = true; 172959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("x86")) { 173959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle useArchX86 = true; 174959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("x86-64")) { 175959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle useArchX86_64 = true; 176959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("mips")) { 177959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle useArchMips = true; 178959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("mips64")) { 179959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle useArchMips64 = true; 180959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("mutate-limit")) { 181959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mutateLimit = true; 182959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("report-unique")) { 183959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle reportUnique = true; 184959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("dump-output")) { 185959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle dumpOutput = true; 186959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("dump-verify")) { 187959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle dumpVerify = true; 188959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("short-timeouts")) { 189959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle shortTimeouts = true; 190959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("skip-mutation")) { 191959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle skipMutation = true; 192959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("dump-mutations")) { 193959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle dumpMutations = true; 194959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("load-mutations")) { 195959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle loadMutations = true; 196959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("one-mutation")) { 197959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle methodMutations = 1; 198959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle minMethods = 1; 199959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle maxMethods = 1; 200959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (flag.equals("help")) { 201959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle usage(); 202959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else { 203959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("Unrecognised flag: --" + flag); 204959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle usage(); 205959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 206959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 207959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 208959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 209959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Given a key-value option (one that features an =), handle it 210959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * accordingly. Report an error and print usage info if the key is not 211959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * recognised. 212959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 213959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private static void handleKeyValueOption(String key, String value) { 214959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (key.equals("input")) { 215959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle inputFileList.add(value); 216959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (key.equals("inputs")) { 217959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle File folder = new File(value); 218959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (folder.listFiles() == null) { 219959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("Specified argument to --inputs is not a directory!"); 220959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 221959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (File file : folder.listFiles()) { 222959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle String inputName = value + "/" + file.getName(); 223959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always("Adding " + inputName + " to input seed files."); 224959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle inputFileList.add(inputName); 225959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 226959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (key.equals("output")) { 227959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle outputFile = value; 228959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (key.equals("seed")) { 229959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle rngSeed = Long.parseLong(value); 230959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle usingProvidedSeed = true; 231959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (key.equals("method-mutations")) { 232959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle methodMutations = Integer.parseInt(value); 233959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (key.equals("min-methods")) { 234959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle minMethods = Integer.parseInt(value); 235959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (key.equals("max-methods")) { 236959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle maxMethods = Integer.parseInt(value); 237959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (key.equals("repeat")) { 238959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle repeat = Integer.parseInt(value); 239959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (key.equals("log")) { 240959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.setLoggingLevel(LogTag.valueOf(value.toUpperCase())); 241959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (key.equals("likelihoods")) { 242959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle setupMutationLikelihoodTable(value); 243959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (key.equals("dump-mutations")) { 244959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle dumpMutations = true; 245959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle dumpMutationsFile = value; 246959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (key.equals("load-mutations")) { 247959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle loadMutations = true; 248959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle loadMutationsFile = value; 249959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (key.equals("report")) { 250959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle reportLogFile = value; 251959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (key.equals("unique-db")) { 252959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle uniqueDatabaseFile = value; 253959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (key.equals("execute-class")) { 254959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle executeClass = value; 255959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (key.equals("device")) { 256959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle deviceName = value; 257959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle usingSpecificDevice = true; 258959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else if (key.equals("execute-dir")) { 259959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle executeDirectory = value; 260959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else { 261959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("Unrecognised key: --" + key); 262959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle usage(); 263959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 264959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 265959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 266959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private static void setupMutationLikelihoodTable(String tableFilename) { 267959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle try { 268959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle BufferedReader reader = new BufferedReader(new FileReader(tableFilename)); 269959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle String line = reader.readLine(); 270959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle while (line != null) { 271959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle line = line.replaceAll("\\s+", " "); 272959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle String[] entries = line.split(" "); 273959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle String name = entries[0].toLowerCase(); 274959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int likelihood = Integer.parseInt(entries[1]); 275959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (likelihood > 100) { 276959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle likelihood = 100; 277959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 278959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (likelihood < 0) { 279959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle likelihood = 0; 280959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 281959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle mutationLikelihoods.put(name, likelihood); 282959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle line = reader.readLine(); 283959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 284959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle reader.close(); 285959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } catch (FileNotFoundException e) { 286959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("Unable to open mutation probability table file: " + tableFilename); 287959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } catch (IOException e) { 288959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("Unable to read mutation probability table file: " + tableFilename); 289959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 290959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 291959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 292959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 293959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Called by the DexFuzz class during program initialisation to parse 294959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * the program's command line arguments. 295959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * @return If options were successfully read and validated. 296959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 297959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle public static boolean readOptions(String[] args) { 298959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle for (String arg : args) { 299959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (!(arg.startsWith("--"))) { 300959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("Unrecognised option: " + arg); 301959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle usage(); 302959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 303959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 304959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // cut off the -- 305959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle arg = arg.substring(2); 306959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 307959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // choose between a --X=Y option (keyvalue) and a --X option (flag) 308959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (arg.contains("=")) { 309959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle String[] split = arg.split("="); 310959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle handleKeyValueOption(split[0], split[1]); 311959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else { 312959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle handleFlagOption(arg); 313959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 314959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 315959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 316959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return validateOptions(); 317959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 318959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 319959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle /** 320959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Checks if the current options settings are valid, called after reading 321959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * all options. 322959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * @return If the options are valid or not. 323959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */ 324959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle private static boolean validateOptions() { 325959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Deal with option assumptions. 326959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (inputFileList.isEmpty()) { 327959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle File seedFile = new File("fuzzingseed.dex"); 328959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (seedFile.exists()) { 329959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always("Assuming --input=fuzzingseed.dex"); 330959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle inputFileList.add("fuzzingseed.dex"); 331959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else { 332959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.errorAndQuit("No input given, and couldn't find fuzzingseed.dex!"); 333959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return false; 334959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 335959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 336959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 337959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (outputFile.equals("")) { 338959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always("Assuming --output=fuzzingseed_fuzzed.dex"); 339959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle outputFile = "fuzzingseed_fuzzed.dex"; 340959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 341959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 342959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 343959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (mutationLikelihoods.isEmpty()) { 344959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle File likelihoodsFile = new File("likelihoods.txt"); 345959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (likelihoodsFile.exists()) { 346959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always("Assuming --likelihoods=likelihoods.txt "); 347959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle setupMutationLikelihoodTable("likelihoods.txt"); 348959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } else { 349959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.always("Using default likelihoods (see README for values)"); 350959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 351959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 352959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 353959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Now check for hard failures. 354959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (repeat < 1) { 355959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("--repeat must be at least 1!"); 356959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return false; 357959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 358959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (usingProvidedSeed && repeat > 1) { 359959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("Cannot use --repeat with --seed"); 360959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return false; 361959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 362959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (loadMutations && dumpMutations) { 363959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("Cannot both load and dump mutations"); 364959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return false; 365959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 366959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (repeat == 1 && inputFileList.size() > 1) { 367959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("Must use --repeat if you have provided more than one input"); 368959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return false; 369959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 370959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (methodMutations < 0) { 371959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("Cannot use --method-mutations with a negative value."); 372959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return false; 373959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 374959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (minMethods < 0) { 375959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("Cannot use --min-methods with a negative value."); 376959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return false; 377959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 378959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (maxMethods < 0) { 379959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("Cannot use --max-methods with a negative value."); 380959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return false; 381959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 382959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (maxMethods < minMethods) { 383959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("Cannot use --max-methods that's smaller than --min-methods"); 384959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return false; 385959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 386807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle if (executeOnHost && usingSpecificDevice) { 387807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle Log.error("Cannot use --host and --device!"); 388959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return false; 389959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 390959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (execute) { 391807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle // When host-execution mode is specified, we don't need to select an architecture. 392807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle if (!executeOnHost) { 393807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle if (!(useArchArm 394807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle || useArchArm64 395807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle || useArchX86 396807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle || useArchX86_64 397807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle || useArchMips 398807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle || useArchMips64)) { 399807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle Log.error("No architecture to execute on was specified!"); 400807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle return false; 401807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle } 402807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle } else { 403807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle // TODO: Select the correct architecture. For now, just assume x86. 404807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle useArchX86 = true; 405959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 406959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if ((useArchArm || useArchArm64) && (useArchX86 || useArchX86_64)) { 407959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("Did you mean to specify ARM and x86?"); 408959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return false; 409959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 410959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if ((useArchArm || useArchArm64) && (useArchMips || useArchMips64)) { 411959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("Did you mean to specify ARM and MIPS?"); 412959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return false; 413959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 414959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if ((useArchX86 || useArchX86_64) && (useArchMips || useArchMips64)) { 415959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("Did you mean to specify x86 and MIPS?"); 416959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return false; 417959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 418959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle int backends = 0; 419959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (useInterpreter) { 420959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle backends++; 421959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 422959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (useQuick) { 423959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle backends++; 424959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 425959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (useOptimizing) { 426959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle backends++; 427959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 428959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (useArchArm && useArchArm64) { 429959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle // Could just be comparing quick-ARM versus quick-ARM64? 430959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle backends++; 431959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 432959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle if (backends < 2) { 433959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle Log.error("Not enough backends specified! Try --quick --interpreter!"); 434959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return false; 435959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 436959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 437959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle 438959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle return true; 439959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle } 440959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle} 441