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