summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2021-04-08 16:40:57 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2021-04-08 16:40:57 +0000
commite6f5d1ee2edff8e1af22fd86fc8a93b91a20a829 (patch)
tree22f2166ca2b0a3ba6dbee939d75574fd64e13762
parent2235a18908d0fc900cde0448f549e480e919c5cf (diff)
parent5a0381fa7c4042a3d813bb2c5b9bbf33d245aaf4 (diff)
downloadart-pie-security-release.tar.gz
Merge cherrypicks of [14126781, 14126782, 14127202, 14128466, 14127516, 14128057, 14127204, 14128747, 14128708, 14128059, 14128686, 14128127, 14128507, 14128809, 14128810, 14128811, 14128812] into security-aosp-pi-releaseandroid-security-9.0.0_r76android-security-9.0.0_r75android-security-9.0.0_r74android-security-9.0.0_r73android-security-9.0.0_r72android-security-9.0.0_r71android-security-9.0.0_r70android-security-9.0.0_r69pie-security-release
Change-Id: I888b5ee13c99b52a3faafa880aff6549bd90bf04
-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