diff options
Diffstat (limited to 'runtime/oat_file.cc')
| -rw-r--r-- | runtime/oat_file.cc | 104 |
1 files changed, 65 insertions, 39 deletions
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index 9cefcb6b1a..971daf8bbf 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -18,12 +18,12 @@ #include <dlfcn.h> #include <sstream> +#include <string.h> #include "base/bit_vector.h" #include "base/stl_util.h" #include "base/unix_file/fd_file.h" #include "elf_file.h" -#include "implicit_check_options.h" #include "oat.h" #include "mirror/art_method.h" #include "mirror/art_method-inl.h" @@ -80,36 +80,7 @@ OatFile* OatFile::Open(const std::string& filename, } ret.reset(OpenElfFile(file.get(), location, requested_base, false, executable, error_msg)); } - - if (ret.get() == nullptr) { - return nullptr; - } - - // Embedded options check. Right now only implicit checks. - // TODO: Refactor to somewhere else? - const char* implicit_checks_value = ret->GetOatHeader(). - GetStoreValueByKey(ImplicitCheckOptions::kImplicitChecksOatHeaderKey); - - if (implicit_checks_value == nullptr) { - *error_msg = "Did not find implicit checks value."; - return nullptr; - } - - bool explicit_null_checks, explicit_so_checks, explicit_suspend_checks; - if (ImplicitCheckOptions::Parse(implicit_checks_value, &explicit_null_checks, - &explicit_so_checks, &explicit_suspend_checks)) { - // Check whether the runtime agrees with the recorded checks. - if (ImplicitCheckOptions::CheckRuntimeSupport(executable, explicit_null_checks, - explicit_so_checks, explicit_suspend_checks, - error_msg)) { - return ret.release(); - } else { - return nullptr; - } - } else { - *error_msg = "Failed parsing implicit check options."; - return nullptr; - } + return ret.release(); } OatFile* OatFile::OpenWritable(File* file, const std::string& location, std::string* error_msg) { @@ -117,6 +88,11 @@ OatFile* OatFile::OpenWritable(File* file, const std::string& location, std::str return OpenElfFile(file, location, NULL, true, false, error_msg); } +OatFile* OatFile::OpenReadable(File* file, const std::string& location, std::string* error_msg) { + CheckLocation(location); + return OpenElfFile(file, location, NULL, false, false, error_msg); +} + OatFile* OatFile::OpenDlopen(const std::string& elf_filename, const std::string& location, byte* requested_base, @@ -145,7 +121,8 @@ OatFile* OatFile::OpenElfFile(File* file, } OatFile::OatFile(const std::string& location) - : location_(location), begin_(NULL), end_(NULL), dlopen_handle_(NULL) { + : location_(location), begin_(NULL), end_(NULL), dlopen_handle_(NULL), + secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) { CHECK(!location_.empty()); } @@ -325,12 +302,12 @@ bool OatFile::Setup(std::string* error_msg) { return false; } + // Create the OatDexFile and add it to the owning map indexed by the dex file location. OatDexFile* oat_dex_file = new OatDexFile(this, dex_file_location, dex_file_checksum, dex_file_pointer, methods_offsets_pointer); - // Use a StringPiece backed by the oat_dex_file's internal std::string as the key. StringPiece key(oat_dex_file->GetDexFileLocation()); oat_dex_files_.Put(key, oat_dex_file); } @@ -354,30 +331,79 @@ const byte* OatFile::End() const { const OatFile::OatDexFile* OatFile::GetOatDexFile(const char* dex_location, const uint32_t* dex_location_checksum, bool warn_if_not_found) const { - Table::const_iterator it = oat_dex_files_.find(dex_location); - if (it != oat_dex_files_.end()) { - const OatFile::OatDexFile* oat_dex_file = it->second; - if (dex_location_checksum == NULL || - oat_dex_file->GetDexFileLocationChecksum() == *dex_location_checksum) { - return oat_dex_file; + // NOTE: We assume here that the canonical location for a given dex_location never + // changes. If it does (i.e. some symlink used by the filename changes) we may return + // an incorrect OatDexFile. As long as we have a checksum to check, we shall return + // an identical file or fail; otherwise we may see some unpredictable failures. + + // TODO: Additional analysis of usage patterns to see if this can be simplified + // without any performance loss, for example by not doing the first lock-free lookup. + + const OatFile::OatDexFile* oat_dex_file = nullptr; + StringPiece key(dex_location); + // Try to find the key cheaply in the oat_dex_files_ map which holds dex locations + // directly mentioned in the oat file and doesn't require locking. + auto primary_it = oat_dex_files_.find(key); + if (primary_it != oat_dex_files_.end()) { + oat_dex_file = primary_it->second; + DCHECK(oat_dex_file != nullptr); + } else { + // This dex_location is not one of the dex locations directly mentioned in the + // oat file. The correct lookup is via the canonical location but first see in + // the secondary_oat_dex_files_ whether we've looked up this location before. + MutexLock mu(Thread::Current(), secondary_lookup_lock_); + auto secondary_lb = secondary_oat_dex_files_.lower_bound(key); + if (secondary_lb != secondary_oat_dex_files_.end() && key == secondary_lb->first) { + oat_dex_file = secondary_lb->second; // May be nullptr. + } else { + // We haven't seen this dex_location before, we must check the canonical location. + if (UNLIKELY(oat_dex_files_by_canonical_location_.empty())) { + // Lazily fill in the oat_dex_files_by_canonical_location_. + for (const auto& entry : oat_dex_files_) { + const std::string& dex_location = entry.second->GetDexFileLocation(); + string_cache_.emplace_back(DexFile::GetDexCanonicalLocation(dex_location.c_str())); + StringPiece canonical_location_key(string_cache_.back()); + oat_dex_files_by_canonical_location_.Put(canonical_location_key, entry.second); + } + } + std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location); + StringPiece canonical_key(dex_canonical_location); + auto canonical_it = oat_dex_files_by_canonical_location_.find(canonical_key); + if (canonical_it != oat_dex_files_by_canonical_location_.end()) { + oat_dex_file = canonical_it->second; + } // else keep nullptr. + + // Copy the key to the string_cache_ and store the result in secondary map. + string_cache_.emplace_back(key.data(), key.length()); + StringPiece key_copy(string_cache_.back()); + secondary_oat_dex_files_.PutBefore(secondary_lb, key_copy, oat_dex_file); } } + if (oat_dex_file != nullptr && + (dex_location_checksum == nullptr || + oat_dex_file->GetDexFileLocationChecksum() == *dex_location_checksum)) { + return oat_dex_file; + } if (warn_if_not_found) { + std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location); std::string checksum("<unspecified>"); if (dex_location_checksum != NULL) { checksum = StringPrintf("0x%08x", *dex_location_checksum); } LOG(WARNING) << "Failed to find OatDexFile for DexFile " << dex_location + << " ( canonical path " << dex_canonical_location << ")" << " with checksum " << checksum << " in OatFile " << GetLocation(); if (kIsDebugBuild) { for (Table::const_iterator it = oat_dex_files_.begin(); it != oat_dex_files_.end(); ++it) { LOG(WARNING) << "OatFile " << GetLocation() << " contains OatDexFile " << it->second->GetDexFileLocation() + << " (canonical path " << it->first << ")" << " with checksum 0x" << std::hex << it->second->GetDexFileLocationChecksum(); } } } + return NULL; } |