summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCalin Juravle <calin@google.com>2020-11-23 19:21:09 -0800
committerCalin Juravle <calin@google.com>2021-03-31 19:21:28 -0700
commitfaf5aa5271657003fe5371ad1b02e2051821d762 (patch)
treea5f2ee13ed76fc3ccc12f8995743f54cefa8b773
parent340de1c79a208a4faed9d58ce01146eb339b1537 (diff)
Do not accept vdex with dex sections from .dm files
Check that the input vdex does not contain dex files when it originates from dex metadata files. (cherry-pick from commit 046cecfed5a4df1e180e3491ba7b566bf50a2026) (partial cherry-pick from commit 33787687f52798fd5b584edb4c88717d134c367a) (partial cherry-pick from commit 858cfd81c4fddbc950f9be2e3599b15aabaa501a) Bug: 111442216 Bug: 178055795 Test: test-art-host Merged-In: I5b104329af899ea62dc1779800264bad6b5424a4 Change-Id: I5b104329af899ea62dc1779800264bad6b5424a4
-rw-r--r--build/Android.gtest.mk3
-rw-r--r--dex2oat/Android.bp1
-rw-r--r--dex2oat/dex2oat.cc7
-rw-r--r--dex2oat/dex2oat_test.cc112
-rw-r--r--dex2oat/dex2oat_vdex_test.cc135
-rw-r--r--runtime/dex2oat_environment_test.h103
-rw-r--r--test/Dex2oatVdexTestDex/Dex2oatVdexTestDex.java83
-rwxr-xr-xtest/etc/run-test-jar2
8 files changed, 334 insertions, 112 deletions
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index b483e5f6f2..a3cea4c763 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -27,6 +27,7 @@ GTEST_DEX_DIRECTORIES := \
AllFields \
DefaultMethods \
DexToDexDecompiler \
+ Dex2oatVdexTestDex \
ErroneousA \
ErroneousB \
ErroneousInit \
@@ -157,7 +158,7 @@ ART_GTEST_class_table_test_DEX_DEPS := XandY
ART_GTEST_compiler_driver_test_DEX_DEPS := AbstractMethod StaticLeafMethods ProfileTestMultiDex
ART_GTEST_dex_cache_test_DEX_DEPS := Main Packages MethodTypes
ART_GTEST_dexlayout_test_DEX_DEPS := ManyMethods
-ART_GTEST_dex2oat_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS) ManyMethods Statics VerifierDeps MainUncompressed EmptyUncompressed
+ART_GTEST_dex2oat_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS) Dex2oatVdexTestDex ManyMethods Statics VerifierDeps MainUncompressed EmptyUncompressed
ART_GTEST_dex2oat_image_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS) Statics VerifierDeps
ART_GTEST_exception_test_DEX_DEPS := ExceptionHandle
ART_GTEST_hiddenapi_test_DEX_DEPS := HiddenApi
diff --git a/dex2oat/Android.bp b/dex2oat/Android.bp
index b793406ba0..420dddd6c3 100644
--- a/dex2oat/Android.bp
+++ b/dex2oat/Android.bp
@@ -276,6 +276,7 @@ art_cc_test {
],
srcs: [
"dex2oat_test.cc",
+ "dex2oat_vdex_test.cc",
"dex2oat_image_test.cc",
"linker/elf_writer_test.cc",
"linker/image_test.cc",
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index fe927bbc1c..609b806bb9 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1467,6 +1467,11 @@ class Dex2Oat FINAL {
LOG(WARNING) << "Could not open vdex file in DexMetadata archive: " << error_msg;
} else {
input_vdex_file_ = std::make_unique<VdexFile>(input_file.release());
+ if (input_vdex_file_->HasDexSection()) {
+ LOG(ERROR) << "The dex metadata is not allowed to contain dex files";
+ return false;
+ }
+ VLOG(verifier) << "Doing fast verification with vdex from DexMetadata archive";
}
}
}
@@ -3124,6 +3129,8 @@ static dex2oat::ReturnCode Dex2oat(int argc, char** argv) {
// Check early that the result of compilation can be written
if (!dex2oat->OpenFile()) {
+ // Flush close so that the File Guard checks don't fail the assertions.
+ dex2oat->FlushCloseOutputFiles();
return dex2oat::ReturnCode::kOther;
}
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index a229d7dd71..a48d15d40a 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -47,7 +47,7 @@
namespace art {
static constexpr size_t kMaxMethodIds = 65535;
-static constexpr bool kDebugArgs = false;
+
static const char* kDisableCompactDex = "--compact-dex-level=none";
using android::base::StringPrintf;
@@ -59,7 +59,6 @@ class Dex2oatTest : public Dex2oatEnvironmentTest {
output_ = "";
error_msg_ = "";
- success_ = false;
}
protected:
@@ -89,7 +88,7 @@ class Dex2oatTest : public Dex2oatEnvironmentTest {
args.insert(args.end(), extra_args.begin(), extra_args.end());
- int status = Dex2Oat(args, error_msg);
+ int status = Dex2Oat(args, &output_, error_msg);
if (oat_file != nullptr) {
CHECK_EQ(oat_file->FlushClose(), 0) << "Could not flush and close oat file";
}
@@ -175,107 +174,8 @@ class Dex2oatTest : public Dex2oatEnvironmentTest {
EXPECT_EQ(expected, actual);
}
- int Dex2Oat(const std::vector<std::string>& dex2oat_args, std::string* error_msg) {
- Runtime* runtime = Runtime::Current();
-
- const std::vector<gc::space::ImageSpace*>& image_spaces =
- runtime->GetHeap()->GetBootImageSpaces();
- if (image_spaces.empty()) {
- *error_msg = "No image location found for Dex2Oat.";
- return false;
- }
- std::string image_location = image_spaces[0]->GetImageLocation();
-
- std::vector<std::string> argv;
- argv.push_back(runtime->GetCompilerExecutable());
-
- if (runtime->IsJavaDebuggable()) {
- argv.push_back("--debuggable");
- }
- runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
-
- if (!runtime->IsVerificationEnabled()) {
- argv.push_back("--compiler-filter=assume-verified");
- }
-
- if (runtime->MustRelocateIfPossible()) {
- argv.push_back("--runtime-arg");
- argv.push_back("-Xrelocate");
- } else {
- argv.push_back("--runtime-arg");
- argv.push_back("-Xnorelocate");
- }
-
- if (!kIsTargetBuild) {
- argv.push_back("--host");
- }
-
- argv.push_back("--boot-image=" + image_location);
-
- std::vector<std::string> compiler_options = runtime->GetCompilerOptions();
- argv.insert(argv.end(), compiler_options.begin(), compiler_options.end());
-
- argv.insert(argv.end(), dex2oat_args.begin(), dex2oat_args.end());
-
- // We must set --android-root.
- const char* android_root = getenv("ANDROID_ROOT");
- CHECK(android_root != nullptr);
- argv.push_back("--android-root=" + std::string(android_root));
-
- if (kDebugArgs) {
- std::string all_args;
- for (const std::string& arg : argv) {
- all_args += arg + " ";
- }
- LOG(ERROR) << all_args;
- }
-
- int link[2];
-
- if (pipe(link) == -1) {
- return false;
- }
-
- pid_t pid = fork();
- if (pid == -1) {
- return false;
- }
-
- if (pid == 0) {
- // We need dex2oat to actually log things.
- setenv("ANDROID_LOG_TAGS", "*:d", 1);
- dup2(link[1], STDERR_FILENO);
- close(link[0]);
- close(link[1]);
- std::vector<const char*> c_args;
- for (const std::string& str : argv) {
- c_args.push_back(str.c_str());
- }
- c_args.push_back(nullptr);
- execv(c_args[0], const_cast<char* const*>(c_args.data()));
- exit(1);
- UNREACHABLE();
- } else {
- close(link[1]);
- char buffer[128];
- memset(buffer, 0, 128);
- ssize_t bytes_read = 0;
-
- while (TEMP_FAILURE_RETRY(bytes_read = read(link[0], buffer, 128)) > 0) {
- output_ += std::string(buffer, bytes_read);
- }
- close(link[0]);
- int status = -1;
- if (waitpid(pid, &status, 0) != -1) {
- success_ = (status == 0);
- }
- return status;
- }
- }
-
std::string output_ = "";
std::string error_msg_ = "";
- bool success_ = false;
};
class Dex2oatSwapTest : public Dex2oatTest {
@@ -299,7 +199,6 @@ class Dex2oatSwapTest : public Dex2oatTest {
GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, copy);
CheckValidity();
- ASSERT_TRUE(success_);
CheckResult(expect_use);
}
@@ -524,7 +423,6 @@ class Dex2oatVeryLargeTest : public Dex2oatTest {
GenerateOdexForTest(dex_location, odex_location, filter, new_args);
CheckValidity();
- ASSERT_TRUE(success_);
CheckResult(dex_location,
odex_location,
app_image_file,
@@ -748,7 +646,6 @@ class Dex2oatLayoutTest : public Dex2oatTest {
/* use_fd */ false,
/* num_profile_classes */ 0);
CheckValidity();
- ASSERT_TRUE(success_);
// Don't check the result since CheckResult relies on the class being in the profile.
image_file_empty_profile = GetImageObjectSectionSize(app_image_file);
EXPECT_GT(image_file_empty_profile, 0u);
@@ -761,7 +658,6 @@ class Dex2oatLayoutTest : public Dex2oatTest {
/* use_fd */ false,
/* num_profile_classes */ 1);
CheckValidity();
- ASSERT_TRUE(success_);
CheckResult(dex_location, odex_location, app_image_file);
if (app_image) {
@@ -807,7 +703,6 @@ class Dex2oatLayoutTest : public Dex2oatTest {
}
ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
CheckValidity();
- ASSERT_TRUE(success_);
}
void CheckResult(const std::string& dex_location,
@@ -929,7 +824,6 @@ class Dex2oatUnquickenTest : public Dex2oatTest {
}
ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
CheckResult(dex_location, odex_location);
- ASSERT_TRUE(success_);
}
void RunUnquickenMultiDexCDex() {
@@ -972,7 +866,6 @@ class Dex2oatUnquickenTest : public Dex2oatTest {
ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
ASSERT_EQ(vdex_file2->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
CheckResult(dex_location, odex_location2);
- ASSERT_TRUE(success_);
}
void CheckResult(const std::string& dex_location, const std::string& odex_location) {
@@ -2003,7 +1896,6 @@ TEST_F(Dex2oatTest, QuickenedInput) {
/* use_fd */ true);
}
ASSERT_EQ(vdex_unquickened->Flush(), 0) << "Could not flush and close vdex file";
- ASSERT_TRUE(success_);
{
// Check that hte vdex has one dex and compare it to the original one.
std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location2.c_str(),
diff --git a/dex2oat/dex2oat_vdex_test.cc b/dex2oat/dex2oat_vdex_test.cc
new file mode 100644
index 0000000000..0eddab6190
--- /dev/null
+++ b/dex2oat/dex2oat_vdex_test.cc
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+#include <vector>
+
+#include "common_runtime_test.h"
+#include "dex2oat_environment_test.h"
+
+#include "vdex_file.h"
+#include "verifier/verifier_deps.h"
+#include "ziparchive/zip_writer.h"
+
+namespace art {
+
+using verifier::VerifierDeps;
+
+class Dex2oatVdexTest : public Dex2oatEnvironmentTest {
+ public:
+ void TearDown() override {
+ Dex2oatEnvironmentTest::TearDown();
+
+ output_ = "";
+ error_msg_ = "";
+ opened_vdex_files_.clear();
+ }
+
+ protected:
+ bool RunDex2oat(const std::string& dex_location,
+ const std::string& odex_location,
+ bool copy_dex_files = false,
+ const std::vector<std::string>& extra_args = {}) {
+ std::vector<std::string> args;
+ args.push_back("--dex-file=" + dex_location);
+ args.push_back("--oat-file=" + odex_location);
+ args.push_back("--compiler-filter=" +
+ CompilerFilter::NameOfFilter(CompilerFilter::Filter::kVerify));
+ args.push_back("--runtime-arg");
+ args.push_back("-Xnorelocate");
+ if (!copy_dex_files) {
+ args.push_back("--copy-dex-files=false");
+ }
+ args.push_back("--runtime-arg");
+ args.push_back("-verbose:verifier,compiler");
+ // Use a single thread to facilitate debugging. We only compile tiny dex files.
+ args.push_back("-j1");
+
+ args.insert(args.end(), extra_args.begin(), extra_args.end());
+
+ return Dex2Oat(args, &output_, &error_msg_) == 0;
+ }
+
+ void CreateDexMetadata(const std::string& vdex, const std::string& out_dm) {
+ // Read the vdex bytes.
+ std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex.c_str()));
+ std::vector<uint8_t> data(vdex_file->GetLength());
+ ASSERT_TRUE(vdex_file->ReadFully(data.data(), data.size()));
+
+ // Zip the content.
+ FILE* file = fopen(out_dm.c_str(), "wb");
+ ZipWriter writer(file);
+ writer.StartEntry("primary.vdex", ZipWriter::kAlign32);
+ writer.WriteBytes(data.data(), data.size());
+ writer.FinishEntry();
+ writer.Finish();
+ fflush(file);
+ fclose(file);
+ }
+
+ std::string GetFilename(const std::unique_ptr<const DexFile>& dex_file) {
+ const std::string& str = dex_file->GetLocation();
+ size_t idx = str.rfind('/');
+ if (idx == std::string::npos) {
+ return str;
+ }
+ return str.substr(idx + 1);
+ }
+
+ std::string GetOdex(const std::unique_ptr<const DexFile>& dex_file,
+ const std::string& suffix = "") {
+ return GetScratchDir() + "/" + GetFilename(dex_file) + suffix + ".odex";
+ }
+
+ std::string GetVdex(const std::unique_ptr<const DexFile>& dex_file,
+ const std::string& suffix = "") {
+ return GetScratchDir() + "/" + GetFilename(dex_file) + suffix + ".vdex";
+ }
+
+ std::string output_;
+ std::string error_msg_;
+ std::vector<std::unique_ptr<VdexFile>> opened_vdex_files_;
+};
+
+// Check that if the input dm does contain dex files then the compilation fails
+TEST_F(Dex2oatVdexTest, VerifyPublicSdkStubsWithDexFiles) {
+ std::string error_msg;
+
+ // Dex2oatVdexTestDex is the subject app using normal APIs found in the boot classpath.
+ std::unique_ptr<const DexFile> dex_file(OpenTestDexFile("Dex2oatVdexTestDex"));
+
+ // Compile the subject app using the predefined API-stubs
+ ASSERT_TRUE(RunDex2oat(
+ dex_file->GetLocation(),
+ GetOdex(dex_file),
+ /*copy_dex_files=*/ true));
+
+ // Create the .dm file with the output.
+ std::string dm_file = GetScratchDir() + "/base.dm";
+ CreateDexMetadata(GetVdex(dex_file), dm_file);
+ std::vector<std::string> extra_args;
+ extra_args.push_back("--dm-file=" + dm_file);
+
+ // Recompile again with the .dm file which contains a vdex with code.
+ // The compilation should fail.
+ ASSERT_FALSE(RunDex2oat(
+ dex_file->GetLocation(),
+ GetOdex(dex_file, "v2"),
+ /*copy_dex_files=*/ true,
+ extra_args));
+}
+
+} // namespace art
diff --git a/runtime/dex2oat_environment_test.h b/runtime/dex2oat_environment_test.h
index 00a95cc7bd..08c7e0ca3f 100644
--- a/runtime/dex2oat_environment_test.h
+++ b/runtime/dex2oat_environment_test.h
@@ -39,6 +39,8 @@
namespace art {
+static constexpr bool kDebugArgs = false;
+
// Test class that provides some helpers to set a test up for compilation using dex2oat.
class Dex2oatEnvironmentTest : public CommonRuntimeTest {
public:
@@ -203,6 +205,107 @@ class Dex2oatEnvironmentTest : public CommonRuntimeTest {
return odex_dir_;
}
+ int Dex2Oat(
+ const std::vector<std::string>& dex2oat_args,
+ std::string* output,
+ std::string* error_msg) {
+ Runtime* runtime = Runtime::Current();
+
+ const std::vector<gc::space::ImageSpace*>& image_spaces =
+ runtime->GetHeap()->GetBootImageSpaces();
+ if (image_spaces.empty()) {
+ *error_msg = "No image location found for Dex2Oat.";
+ return false;
+ }
+ std::string image_location = image_spaces[0]->GetImageLocation();
+
+ std::vector<std::string> argv;
+ argv.push_back(runtime->GetCompilerExecutable());
+
+ if (runtime->IsJavaDebuggable()) {
+ argv.push_back("--debuggable");
+ }
+ runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
+
+ if (!runtime->IsVerificationEnabled()) {
+ argv.push_back("--compiler-filter=assume-verified");
+ }
+
+ if (runtime->MustRelocateIfPossible()) {
+ argv.push_back("--runtime-arg");
+ argv.push_back("-Xrelocate");
+ } else {
+ argv.push_back("--runtime-arg");
+ argv.push_back("-Xnorelocate");
+ }
+
+ if (!kIsTargetBuild) {
+ argv.push_back("--host");
+ }
+
+ argv.push_back("--boot-image=" + image_location);
+
+ std::vector<std::string> compiler_options = runtime->GetCompilerOptions();
+ argv.insert(argv.end(), compiler_options.begin(), compiler_options.end());
+
+ argv.insert(argv.end(), dex2oat_args.begin(), dex2oat_args.end());
+
+ // We must set --android-root.
+ const char* android_root = getenv("ANDROID_ROOT");
+ CHECK(android_root != nullptr);
+ argv.push_back("--android-root=" + std::string(android_root));
+
+ if (kDebugArgs) {
+ std::string all_args;
+ for (const std::string& arg : argv) {
+ all_args += arg + " ";
+ }
+ LOG(ERROR) << all_args;
+ }
+
+ int link[2];
+
+ if (pipe(link) == -1) {
+ ::testing::AssertionFailure() << "Failed to pipe: " << *error_msg;
+ }
+
+ pid_t pid = fork();
+ if (pid == -1) {
+ ::testing::AssertionFailure() << "Failed to fork: " << *error_msg;
+ }
+
+ if (pid == 0) {
+ // We need dex2oat to actually log things.
+ setenv("ANDROID_LOG_TAGS", "*:d", 1);
+ dup2(link[1], STDERR_FILENO);
+ close(link[0]);
+ close(link[1]);
+ std::vector<const char*> c_args;
+ for (const std::string& str : argv) {
+ c_args.push_back(str.c_str());
+ }
+ c_args.push_back(nullptr);
+ execv(c_args[0], const_cast<char* const*>(c_args.data()));
+ exit(1);
+ UNREACHABLE();
+ } else {
+ close(link[1]);
+ char buffer[128];
+ memset(buffer, 0, 128);
+ ssize_t bytes_read = 0;
+
+ while (TEMP_FAILURE_RETRY(bytes_read = read(link[0], buffer, 128)) > 0) {
+ *output += std::string(buffer, bytes_read);
+ }
+ close(link[0]);
+ int status = -1;
+ if (waitpid(pid, &status, 0) != -1) {
+ ::testing::AssertionFailure() << "dex2oat fork/exec failed: " << *error_msg;
+ }
+ return status;
+ }
+ }
+
private:
std::string scratch_dir_;
std::string odex_oat_dir_;
diff --git a/test/Dex2oatVdexTestDex/Dex2oatVdexTestDex.java b/test/Dex2oatVdexTestDex/Dex2oatVdexTestDex.java
new file mode 100644
index 0000000000..e4862bdd81
--- /dev/null
+++ b/test/Dex2oatVdexTestDex/Dex2oatVdexTestDex.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Check that the classes using publicly listed APIS are verified.
+ */
+
+class AccessPublicCtor {
+ public Integer foo() {
+ return new Integer(1);
+ }
+}
+
+class AccessPublicMethod {
+ public double foo(Integer i) {
+ return i.doubleValue();
+ }
+}
+
+class AccessPublicMethodFromParent {
+ public void foo(Integer i) {
+ i.notify();
+ }
+}
+
+class AccessPublicStaticMethod {
+ public Integer foo() {
+ return Integer.getInteger("1");
+ }
+}
+
+class AccessPublicStaticField {
+ public int foo() {
+ return Integer.BYTES;
+ }
+}
+
+/**
+ * Check that the classes using non publicly listed APIS are not verified.
+ */
+
+class AccessNonPublicCtor {
+ public Integer foo() {
+ return new Integer("1");
+ }
+}
+
+class AccessNonPublicMethod {
+ public float foo(Integer i) {
+ return i.floatValue();
+ }
+}
+
+class AccessNonPublicMethodFromParent {
+ public void foo(Integer i) {
+ i.notifyAll();
+ }
+}
+
+class AccessNonPublicStaticMethod {
+ public Integer foo() {
+ return Integer.getInteger("1", 0);
+ }
+}
+
+class AccessNonPublicStaticField {
+ public Class foo() {
+ return Integer.TYPE;
+ }
+}
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index fa6ef54c93..b3965c91c3 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -750,7 +750,7 @@ if [ "$PREBUILD" = "y" ]; then
elif [ "$TEST_DM" = "y" ]; then
dex2oat_cmdline="${dex2oat_cmdline} --output-vdex=$DEX_LOCATION/oat/$ISA/primary.vdex"
dm_cmdline="zip -qj $DEX_LOCATION/oat/$ISA/$TEST_NAME.dm $DEX_LOCATION/oat/$ISA/primary.vdex"
- vdex_cmdline="${dex2oat_cmdline} --dump-timings --dm-file=$DEX_LOCATION/oat/$ISA/$TEST_NAME.dm"
+ vdex_cmdline="${dex2oat_cmdline} --copy-dex-files=false --dump-timings --dm-file=$DEX_LOCATION/oat/$ISA/$TEST_NAME.dm"
elif [ "$PROFILE" = "y" ] || [ "$RANDOM_PROFILE" = "y" ]; then
vdex_cmdline="${dex2oat_cmdline} --input-vdex=$DEX_LOCATION/oat/$ISA/$TEST_NAME.vdex --output-vdex=$DEX_LOCATION/oat/$ISA/$TEST_NAME.vdex"
fi