diff options
Diffstat (limited to 'runtime/oat_file.cc')
| -rw-r--r-- | runtime/oat_file.cc | 87 |
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() {} |