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.executors;
18959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
19959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.ExecutionResult;
20959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.Options;
21959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.StreamConsumer;
22959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.listeners.BaseListener;
23959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
24959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle/**
25959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Base class containing the common methods for executing a particular backend of ART.
26959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */
27959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepublic abstract class Executor {
28959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  private StreamConsumer outputConsumer;
29959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  private StreamConsumer errorConsumer;
30959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
31959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  protected ExecutionResult executionResult;
32959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  protected String executeClass;
33959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
34959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  // Set by subclasses.
35959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  protected String name;
36959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  protected int timeout;
37959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  protected BaseListener listener;
38959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  protected String testLocation;
39959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  protected Architecture architecture;
40959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  protected Device device;
41807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle  private boolean needsCleanCodeCache;
42959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
43959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  protected Executor(String name, int timeout, BaseListener listener, Architecture architecture,
44807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle      Device device, boolean needsCleanCodeCache) {
45959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    executeClass = Options.executeClass;
46959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
47959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (Options.shortTimeouts) {
48959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      this.timeout = 2;
49959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    } else {
50959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      this.timeout = timeout;
51959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
52959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
53959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    this.name = name;
54959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    this.listener = listener;
55959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    this.architecture = architecture;
56959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    this.device = device;
57807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle    this.needsCleanCodeCache = needsCleanCodeCache;
58959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
59807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle    if (Options.executeOnHost) {
60807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle      this.testLocation = System.getProperty("user.dir");
61807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle    } else {
62807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle      this.testLocation = Options.executeDirectory;
63807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle    }
64959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
65959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    outputConsumer = new StreamConsumer();
66959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    outputConsumer.start();
67959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    errorConsumer = new StreamConsumer();
68959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    errorConsumer.start();
69959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
70959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
71959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
72959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Called by subclass Executors in their execute() implementations.
73959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
74807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle  protected ExecutionResult executeCommandWithTimeout(String command, boolean captureOutput) {
75959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    String timeoutString = "timeout " + timeout + " ";
76807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle    return device.executeCommand(timeoutString + device.getExecutionShellPrefix() + command,
77807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle        captureOutput, outputConsumer, errorConsumer);
78959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
79959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
80959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
81959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Call this to make sure the StreamConsumer threads are stopped.
82959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
83959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public void shutdown() {
84959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    outputConsumer.shutdown();
85959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    errorConsumer.shutdown();
86959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
87959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
88959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
89959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Called by the Fuzzer after each execution has finished, to clear the results.
90959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
91959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public void reset() {
92959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    executionResult = null;
93959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
94959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
95959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
96959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Called by the Fuzzer to verify the mutated program using the host-side dex2oat.
97959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
98959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public boolean verifyOnHost(String programName) {
99959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    StringBuilder commandBuilder = new StringBuilder();
100959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    commandBuilder.append("dex2oat ");
101959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
102807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle    commandBuilder.append("--instruction-set=").append(architecture.asString());
103959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    commandBuilder.append(" --instruction-set-features=default ");
104959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
105959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // Select the correct boot image.
106807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle    commandBuilder.append("--boot-image=").append(device.getAndroidProductOut());
107959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (device.noBootImageAvailable()) {
108959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      commandBuilder.append("/data/art-test/core.art ");
109959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    } else {
110959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      commandBuilder.append("/system/framework/boot.art ");
111959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
112959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
113959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    commandBuilder.append("--oat-file=output.oat ");
114807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle    commandBuilder.append("--android-root=").append(device.getAndroidHostOut()).append(" ");
115959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    commandBuilder.append("--runtime-arg -classpath ");
116959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    commandBuilder.append("--runtime-arg ").append(programName).append(" ");
117959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    commandBuilder.append("--dex-file=").append(programName).append(" ");
118959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    commandBuilder.append("--compiler-filter=interpret-only --runtime-arg -Xnorelocate ");
119959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
120807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle    ExecutionResult verificationResult = device.executeCommand(commandBuilder.toString(), true,
121807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle        outputConsumer, errorConsumer);
122959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
123959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    boolean success = true;
124959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
125959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (verificationResult.isSigabort()) {
126959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      listener.handleHostVerificationSigabort(verificationResult);
127959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      success = false;
128959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
129959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
130959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (success) {
131959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      // Search for a keyword that indicates verification was not successful.
132959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      // TODO: Determine if dex2oat crashed?
133959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      for (String line : verificationResult.error) {
134959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        if (line.contains("Verification error")
135959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle            || line.contains("Failure to verify dex file")) {
136959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle          success = false;
137959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        }
138959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        if (Options.dumpVerify) {
139959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle          // Strip out the start of the log lines.
140959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle          listener.handleDumpVerify(line.replaceFirst(".*(cc|h):\\d+] ",  ""));
141959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        }
142959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      }
143959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
144959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
145959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (!success) {
146959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      listener.handleFailedHostVerification(verificationResult);
147959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
148959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
149807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle    device.executeCommand("rm output.oat", false);
150959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
151959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return success;
152959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
153959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
154959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
155959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Called by the Fuzzer to upload the program to the target device.
156959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
157807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle  public void prepareProgramForExecution(String programName) {
158807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle    if (!Options.executeOnHost) {
159807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle      device.pushProgramToDevice(programName, testLocation);
160807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle    }
161807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle
162807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle    if (needsCleanCodeCache) {
163807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle      // Get the device to clean the code cache
164807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle      device.cleanCodeCache(architecture, testLocation, programName);
165807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle    }
166959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
167959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
168959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
169959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Executor subclasses need to override this, to construct their arguments for dalvikvm
170959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * invocation correctly.
171959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
172959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public abstract void execute(String programName);
173959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
174959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
175959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Fuzzer.checkForArchitectureSplit() will use this determine the architecture of the Executor.
176959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
177959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public Architecture getArchitecture() {
178959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return architecture;
179959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
180959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
181959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
182959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Used by the Fuzzer to get result of execution.
183959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
184959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public ExecutionResult getResult() {
185959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return executionResult;
186959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
187959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
188959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
189959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Because dex2oat can accept a program with soft errors on the host, and then fail after
190959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * performing hard verification on the target, we need to check if the Executor detected
191959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * a target verification failure, before doing anything else with the resulting output.
192959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Used by the Fuzzer.
193959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
194807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle  public boolean didTargetVerify() {
195959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // TODO: Remove this once host-verification can be forced to always fail?
196807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle    String output = executionResult.getFlattenedAll();
197807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle    if (output.contains("VerifyError") || output.contains("Verification failed on class")) {
198959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      return false;
199959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
200959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return true;
201959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
202959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
203959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public String getName() {
204959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return name;
205959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
206807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle
207807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle  public void finishedWithProgramOnDevice() {
208807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle    device.resetProgramPushed();
209807f17831e2749d5765599df1c9fbc58af3c6c7cStephen Kyle  }
210959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle}
211