summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/class_linker.cc21
-rw-r--r--runtime/oat_file.cc12
-rw-r--r--runtime/oat_file.h4
-rw-r--r--runtime/runtime.cc69
-rw-r--r--test/119-noimage-patchoat/expected.txt6
-rw-r--r--test/119-noimage-patchoat/info.txt1
-rw-r--r--test/119-noimage-patchoat/run36
-rw-r--r--test/119-noimage-patchoat/src/Main.java38
8 files changed, 180 insertions, 7 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index c696089ad9..4123fc6398 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1168,6 +1168,7 @@ const OatFile* ClassLinker::FindOatFileContainingDexFileFromDexLocation(
error_msg.c_str()));
return nullptr;
} else if (!oat_file->IsExecutable() &&
+ Runtime::Current()->GetHeap()->HasImageSpace() &&
!VerifyOatImageChecksum(oat_file.get(), isa)) {
error_msgs->push_back(StringPrintf("Failed to verify non-executable oat file '%s' found for "
"dex location '%s'. Image checksum incorrect.",
@@ -1250,6 +1251,7 @@ const OatFile* ClassLinker::OpenOatFileFromDexLocation(const std::string& dex_lo
std::string odex_error_msg;
bool should_patch_system = false;
bool odex_checksum_verified = false;
+ bool have_system_odex = false;
{
// There is a high probability that these both these oat files map similar/the same address
// spaces so we must scope them like this so they each gets its turn.
@@ -1260,14 +1262,18 @@ const OatFile* ClassLinker::OpenOatFileFromDexLocation(const std::string& dex_lo
&odex_error_msg)) {
error_msgs->push_back(odex_error_msg);
return odex_oat_file.release();
- } else if (odex_checksum_verified) {
- // We can just relocate
- should_patch_system = true;
- odex_error_msg = "Image Patches are incorrect";
+ } else {
+ if (odex_checksum_verified) {
+ // We can just relocate
+ should_patch_system = true;
+ odex_error_msg = "Image Patches are incorrect";
+ }
+ if (odex_oat_file.get() != nullptr) {
+ have_system_odex = true;
+ }
}
}
-
std::string cache_error_msg;
bool should_patch_cache = false;
bool cache_checksum_verified = false;
@@ -1303,6 +1309,8 @@ const OatFile* ClassLinker::OpenOatFileFromDexLocation(const std::string& dex_lo
CHECK(have_dalvik_cache);
ret = PatchAndRetrieveOat(cache_filename, cache_filename, image_location, isa, &error_msg);
}
+ } else if (have_system_odex) {
+ ret = GetInterpretedOnlyOat(odex_filename, isa, &error_msg);
}
}
if (ret == nullptr && have_dalvik_cache && OS::FileExists(cache_filename.c_str())) {
@@ -1352,7 +1360,8 @@ const OatFile* ClassLinker::GetInterpretedOnlyOat(const std::string& oat_path,
if (output.get() == nullptr) {
return nullptr;
}
- if (VerifyOatImageChecksum(output.get(), isa)) {
+ if (!Runtime::Current()->GetHeap()->HasImageSpace() ||
+ VerifyOatImageChecksum(output.get(), isa)) {
return output.release();
} else {
*error_msg = StringPrintf("Could not use oat file '%s', image checksum failed to verify.",
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 50dfe2109f..d179a960b5 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -24,6 +24,7 @@
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "elf_file.h"
+#include "elf_utils.h"
#include "oat.h"
#include "mirror/art_method.h"
#include "mirror/art_method-inl.h"
@@ -40,6 +41,17 @@ void OatFile::CheckLocation(const std::string& location) {
CHECK(!location.empty());
}
+OatFile* OatFile::OpenWithElfFile(ElfFile* elf_file,
+ const std::string& location,
+ std::string* error_msg) {
+ std::unique_ptr<OatFile> oat_file(new OatFile(location, false));
+ oat_file->elf_file_.reset(elf_file);
+ Elf32_Shdr* hdr = elf_file->FindSectionByName(".rodata");
+ oat_file->begin_ = elf_file->Begin() + hdr->sh_offset;
+ oat_file->end_ = elf_file->Begin() + hdr->sh_size + hdr->sh_offset;
+ return oat_file->Setup(error_msg) ? oat_file.release() : nullptr;
+}
+
OatFile* OatFile::OpenMemory(std::vector<uint8_t>& oat_contents,
const std::string& location,
std::string* error_msg) {
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 8535bf4133..5b24e8fd6f 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -40,6 +40,10 @@ class OatHeader;
class OatFile {
public:
+ // Opens an oat file contained within the given elf file. This is always opened as
+ // non-executable at the moment.
+ static OatFile* OpenWithElfFile(ElfFile* elf_file, const std::string& location,
+ std::string* error_msg);
// Open an oat file. Returns NULL on failure. Requested base can
// optionally be used to request where the file should be loaded.
static OatFile* Open(const std::string& filename,
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 3fc6ad53d2..d05d031335 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -46,6 +46,7 @@
#include "atomic.h"
#include "class_linker.h"
#include "debugger.h"
+#include "elf_file.h"
#include "fault_handler.h"
#include "gc/accounting/card_table-inl.h"
#include "gc/heap.h"
@@ -66,6 +67,7 @@
#include "native_bridge_art_interface.h"
#include "parsed_options.h"
#include "oat_file.h"
+#include "os.h"
#include "quick/quick_method_frame_info.h"
#include "reflection.h"
#include "ScopedLocalRef.h"
@@ -547,9 +549,74 @@ void Runtime::StartDaemonThreads() {
VLOG(startup) << "Runtime::StartDaemonThreads exiting";
}
+static bool OpenDexFilesFromImage(const std::vector<std::string>& dex_filenames,
+ const std::string& image_location,
+ std::vector<const DexFile*>& dex_files,
+ size_t* failures) {
+ std::string system_filename;
+ bool has_system = false;
+ std::string cache_filename_unused;
+ bool dalvik_cache_exists_unused;
+ bool has_cache_unused;
+ bool found_image = gc::space::ImageSpace::FindImageFilename(image_location.c_str(),
+ kRuntimeISA,
+ &system_filename,
+ &has_system,
+ &cache_filename_unused,
+ &dalvik_cache_exists_unused,
+ &has_cache_unused);
+ *failures = 0;
+ if (!found_image || !has_system) {
+ return false;
+ }
+ std::string error_msg;
+ // We are falling back to non-executable use of the oat file because patching failed, presumably
+ // due to lack of space.
+ std::string oat_filename = ImageHeader::GetOatLocationFromImageLocation(system_filename.c_str());
+ std::string oat_location = ImageHeader::GetOatLocationFromImageLocation(image_location.c_str());
+ std::unique_ptr<File> file(OS::OpenFileForReading(oat_filename.c_str()));
+ if (file.get() == nullptr) {
+ return false;
+ }
+ std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file.release(), false, false, &error_msg));
+ if (elf_file.get() == nullptr) {
+ return false;
+ }
+ std::unique_ptr<OatFile> oat_file(OatFile::OpenWithElfFile(elf_file.release(), oat_location,
+ &error_msg));
+ if (oat_file.get() == nullptr) {
+ LOG(INFO) << "Unable to use '" << oat_filename << "' because " << error_msg;
+ return false;
+ }
+
+ std::vector<const OatFile::OatDexFile*> oat_dex_files = oat_file->GetOatDexFiles();
+ for (size_t i = 0; i < oat_dex_files.size(); i++) {
+ const OatFile::OatDexFile* oat_dex_file = oat_dex_files[i];
+ if (oat_dex_file == nullptr) {
+ *failures += 1;
+ continue;
+ }
+ const DexFile* dex_file = oat_dex_file->OpenDexFile(&error_msg);
+ if (dex_file == nullptr) {
+ *failures += 1;
+ } else {
+ dex_files.push_back(dex_file);
+ }
+ }
+ Runtime::Current()->GetClassLinker()->RegisterOatFile(oat_file.release());
+ return true;
+}
+
+
static size_t OpenDexFiles(const std::vector<std::string>& dex_filenames,
+ const std::string& image_location,
std::vector<const DexFile*>& dex_files) {
size_t failure_count = 0;
+ if (!image_location.empty() && OpenDexFilesFromImage(dex_filenames, image_location, dex_files,
+ &failure_count)) {
+ return failure_count;
+ }
+ failure_count = 0;
for (size_t i = 0; i < dex_filenames.size(); i++) {
const char* dex_filename = dex_filenames[i].c_str();
std::string error_msg;
@@ -713,7 +780,7 @@ bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized)
std::vector<std::string> dex_filenames;
Split(boot_class_path_string_, ':', dex_filenames);
std::vector<const DexFile*> boot_class_path;
- OpenDexFiles(dex_filenames, boot_class_path);
+ OpenDexFiles(dex_filenames, options->image_, boot_class_path);
class_linker_->InitWithoutImage(boot_class_path);
// TODO: Should we move the following to InitWithoutImage?
SetInstructionSet(kRuntimeISA);
diff --git a/test/119-noimage-patchoat/expected.txt b/test/119-noimage-patchoat/expected.txt
new file mode 100644
index 0000000000..e864268a38
--- /dev/null
+++ b/test/119-noimage-patchoat/expected.txt
@@ -0,0 +1,6 @@
+Run -Xnoimage-dex2oat -Xpatchoat:/system/bin/false
+Has image is false, is image dex2oat enabled is false.
+Run -Ximage-dex2oat
+Has image is true, is image dex2oat enabled is true.
+Run default
+Has image is true, is image dex2oat enabled is true.
diff --git a/test/119-noimage-patchoat/info.txt b/test/119-noimage-patchoat/info.txt
new file mode 100644
index 0000000000..6b853688dd
--- /dev/null
+++ b/test/119-noimage-patchoat/info.txt
@@ -0,0 +1 @@
+Test that disables patchoat'ing the image.
diff --git a/test/119-noimage-patchoat/run b/test/119-noimage-patchoat/run
new file mode 100644
index 0000000000..745b0c9475
--- /dev/null
+++ b/test/119-noimage-patchoat/run
@@ -0,0 +1,36 @@
+#!/bin/bash
+#
+# Copyright (C) 2014 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.
+
+# Force relocation otherwise we will just use the already created core.oat/art pair.
+flags="${@/--no-relocate/--relocate}"
+
+if [ $(basename $RUN) == 'host-run-test-jar' ]; then
+ false_bin="/bin/false"
+else
+ false_bin="/system/bin/false"
+fi
+
+# Make sure we can run without an image file,
+echo "Run -Xnoimage-dex2oat -Xpatchoat:/system/bin/false"
+${RUN} ${flags} ${BPATH} --runtime-option -Xnoimage-dex2oat --runtime-option -Xpatchoat:${false_bin}
+
+# Make sure we can run with the image file.
+echo "Run -Ximage-dex2oat"
+${RUN} ${flags} ${BPATH} --runtime-option -Ximage-dex2oat
+
+# Make sure we can run with the default settings.
+echo "Run default"
+${RUN} ${flags} ${BPATH}
diff --git a/test/119-noimage-patchoat/src/Main.java b/test/119-noimage-patchoat/src/Main.java
new file mode 100644
index 0000000000..11c736a7d6
--- /dev/null
+++ b/test/119-noimage-patchoat/src/Main.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+public class Main {
+ public static void main(String[] args) {
+ boolean hasImage = hasImage();
+ System.out.println(
+ "Has image is " + hasImage + ", is image dex2oat enabled is "
+ + isImageDex2OatEnabled() + ".");
+
+ if (hasImage && !isImageDex2OatEnabled()) {
+ throw new Error("Image with dex2oat disabled runs with an oat file");
+ } else if (!hasImage && isImageDex2OatEnabled()) {
+ throw new Error("Image with dex2oat enabled runs without an oat file");
+ }
+ }
+
+ static {
+ System.loadLibrary("arttest");
+ }
+
+ private native static boolean hasImage();
+
+ private native static boolean isImageDex2OatEnabled();
+}