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