summaryrefslogtreecommitdiff
path: root/runtime/oat_file.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/oat_file.cc')
-rw-r--r--runtime/oat_file.cc87
1 files changed, 72 insertions, 15 deletions
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index a4a159e0da..e861921130 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -42,9 +42,11 @@
#include "mirror/class.h"
#include "mirror/object-inl.h"
#include "oat_file-inl.h"
+#include "oat_file_manager.h"
#include "os.h"
#include "runtime.h"
#include "utils.h"
+#include "utils/dex_cache_arrays_layout-inl.h"
#include "vmap_table.h"
namespace art {
@@ -115,15 +117,35 @@ OatFile* OatFile::Open(const std::string& filename,
// TODO: Also try when not executable? The issue here could be re-mapping as writable (as
// !executable is a sign that we may want to patch), which may not be allowed for
// various reasons.
- if (kUseDlopen && (kIsTargetBuild || kUseDlopenOnHost) && executable) {
- // Try to use dlopen. This may fail for various reasons, outlined below. We try dlopen, as
- // this will register the oat file with the linker and allows libunwind to find our info.
- ret.reset(OpenDlopen(filename, location, requested_base, abs_dex_location, error_msg));
- if (ret.get() != nullptr) {
- return ret.release();
+ // dlopen always returns the same library if it is already opened on the host. For this reason
+ // we only use dlopen if we are the target or we do not already have the dex file opened. Having
+ // the same library loaded multiple times at different addresses is required for class unloading
+ // and for having dex caches arrays in the .bss section.
+ Runtime* const runtime = Runtime::Current();
+ OatFileManager* const manager = (runtime != nullptr) ? &runtime->GetOatFileManager() : nullptr;
+ if (kUseDlopen && executable) {
+ bool success = kIsTargetBuild;
+ bool reserved_location = false;
+ // Manager may be null if we are running without a runtime.
+ if (!success && kUseDlopenOnHost && manager != nullptr) {
+ // RegisterOatFileLocation returns false if we are not the first caller to register that
+ // location.
+ reserved_location = manager->RegisterOatFileLocation(location);
+ success = reserved_location;
}
- if (kPrintDlOpenErrorMessage) {
- LOG(ERROR) << "Failed to dlopen: " << *error_msg;
+ if (success) {
+ // Try to use dlopen. This may fail for various reasons, outlined below. We try dlopen, as
+ // this will register the oat file with the linker and allows libunwind to find our info.
+ ret.reset(OpenDlopen(filename, location, requested_base, abs_dex_location, error_msg));
+ if (reserved_location) {
+ manager->UnRegisterOatFileLocation(location);
+ }
+ if (ret != nullptr) {
+ return ret.release();
+ }
+ if (kPrintDlOpenErrorMessage) {
+ LOG(ERROR) << "Failed to dlopen: " << *error_msg;
+ }
}
}
@@ -204,6 +226,10 @@ OatFile::OatFile(const std::string& location, bool is_executable)
is_executable_(is_executable), dlopen_handle_(nullptr),
secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) {
CHECK(!location_.empty());
+ Runtime* const runtime = Runtime::Current();
+ if (runtime != nullptr && !runtime->IsAotCompiler()) {
+ runtime->GetOatFileManager().RegisterOatFileLocation(location);
+ }
}
OatFile::~OatFile() {
@@ -211,6 +237,10 @@ OatFile::~OatFile() {
if (dlopen_handle_ != nullptr) {
dlclose(dlopen_handle_);
}
+ Runtime* const runtime = Runtime::Current();
+ if (runtime != nullptr && !runtime->IsAotCompiler()) {
+ runtime->GetOatFileManager().UnRegisterOatFileLocation(location_);
+ }
}
bool OatFile::Dlopen(const std::string& elf_filename, uint8_t* requested_base,
@@ -218,10 +248,7 @@ bool OatFile::Dlopen(const std::string& elf_filename, uint8_t* requested_base,
#ifdef __APPLE__
// The dl_iterate_phdr syscall is missing. There is similar API on OSX,
// but let's fallback to the custom loading code for the time being.
- UNUSED(elf_filename);
- UNUSED(requested_base);
- UNUSED(abs_dex_location);
- UNUSED(error_msg);
+ UNUSED(elf_filename, requested_base, abs_dex_location, error_msg);
return false;
#else
{
@@ -403,6 +430,8 @@ bool OatFile::Setup(const char* abs_dex_location, std::string* error_msg) {
return false;
}
+ size_t pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
+ const uint8_t* dex_cache_arrays = bss_begin_;
uint32_t dex_file_count = GetOatHeader().GetDexFileCount();
oat_dex_files_storage_.reserve(dex_file_count);
for (size_t i = 0; i < dex_file_count; i++) {
@@ -484,6 +513,22 @@ bool OatFile::Setup(const char* abs_dex_location, std::string* error_msg) {
return false;
}
+ const uint8_t* current_dex_cache_arrays = nullptr;
+ if (dex_cache_arrays != nullptr) {
+ DexCacheArraysLayout layout(pointer_size, *header);
+ if (layout.Size() != 0u) {
+ if (static_cast<size_t>(bss_end_ - dex_cache_arrays) < layout.Size()) {
+ *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with "
+ "truncated dex cache arrays, %zd < %zd.",
+ GetLocation().c_str(), i, dex_file_location.c_str(),
+ static_cast<size_t>(bss_end_ - dex_cache_arrays), layout.Size());
+ return false;
+ }
+ current_dex_cache_arrays = dex_cache_arrays;
+ dex_cache_arrays += layout.Size();
+ }
+ }
+
std::string canonical_location = DexFile::GetDexCanonicalLocation(dex_file_location.c_str());
// Create the OatDexFile and add it to the owning container.
@@ -492,7 +537,8 @@ bool OatFile::Setup(const char* abs_dex_location, std::string* error_msg) {
canonical_location,
dex_file_checksum,
dex_file_pointer,
- methods_offsets_pointer);
+ methods_offsets_pointer,
+ current_dex_cache_arrays);
oat_dex_files_storage_.push_back(oat_dex_file);
// Add the location and canonical location (if different) to the oat_dex_files_ table.
@@ -503,6 +549,15 @@ bool OatFile::Setup(const char* abs_dex_location, std::string* error_msg) {
oat_dex_files_.Put(canonical_key, oat_dex_file);
}
}
+
+ if (dex_cache_arrays != bss_end_) {
+ // We expect the bss section to be either empty (dex_cache_arrays and bss_end_
+ // both null) or contain just the dex cache arrays and nothing else.
+ *error_msg = StringPrintf("In oat file '%s' found unexpected bss size bigger by %zd bytes.",
+ GetLocation().c_str(),
+ static_cast<size_t>(bss_end_ - dex_cache_arrays));
+ return false;
+ }
return true;
}
@@ -605,13 +660,15 @@ OatFile::OatDexFile::OatDexFile(const OatFile* oat_file,
const std::string& canonical_dex_file_location,
uint32_t dex_file_location_checksum,
const uint8_t* dex_file_pointer,
- const uint32_t* oat_class_offsets_pointer)
+ const uint32_t* oat_class_offsets_pointer,
+ const uint8_t* dex_cache_arrays)
: oat_file_(oat_file),
dex_file_location_(dex_file_location),
canonical_dex_file_location_(canonical_dex_file_location),
dex_file_location_checksum_(dex_file_location_checksum),
dex_file_pointer_(dex_file_pointer),
- oat_class_offsets_pointer_(oat_class_offsets_pointer) {}
+ oat_class_offsets_pointer_(oat_class_offsets_pointer),
+ dex_cache_arrays_(dex_cache_arrays) {}
OatFile::OatDexFile::~OatDexFile() {}