diff options
-rw-r--r-- | dex2oat/dex2oat.cc | 5 | ||||
-rw-r--r-- | runtime/class_linker.cc | 41 | ||||
-rw-r--r-- | runtime/class_linker.h | 7 | ||||
-rw-r--r-- | runtime/gc/space/image_space.cc | 3 | ||||
-rw-r--r-- | runtime/oat.cc | 15 | ||||
-rw-r--r-- | runtime/oat.h | 10 | ||||
-rw-r--r-- | runtime/oat_file.cc | 4 | ||||
-rw-r--r-- | runtime/oat_file.h | 3 | ||||
-rw-r--r-- | runtime/oat_file_assistant.cc | 8 | ||||
-rw-r--r-- | runtime/runtime.cc | 4 |
10 files changed, 79 insertions, 21 deletions
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index b4a45c654d..3cf458ab5b 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -979,7 +979,10 @@ class Dex2Oat FINAL { oss.str(""); // Reset. oss << kRuntimeISA; key_value_store_->Put(OatHeader::kDex2OatHostKey, oss.str()); - key_value_store_->Put(OatHeader::kPicKey, compile_pic ? "true" : "false"); + key_value_store_->Put(OatHeader::kPicKey, + compile_pic ? OatHeader::kTrueValue : OatHeader::kFalseValue); + key_value_store_->Put(OatHeader::kDebuggableKey, + debuggable ? OatHeader::kTrueValue : OatHeader::kFalseValue); } } diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index b099088e4d..292f830764 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -819,6 +819,34 @@ static void FreeDexFilesInHeap(std::priority_queue<DexFileAndClassPair>* heap) { } } +const OatFile* ClassLinker::GetBootOatFile() { + // To grab the boot oat, look at the dex files in the boot classpath. Any of those is fine, as + // they were all compiled into the same oat file. So grab the first one, which is guaranteed to + // exist if the boot class-path isn't empty. + if (boot_class_path_.empty()) { + return nullptr; + } + const DexFile* boot_dex_file = boot_class_path_[0]; + // Is it from an oat file? + if (boot_dex_file->GetOatDexFile() != nullptr) { + return boot_dex_file->GetOatDexFile()->GetOatFile(); + } + return nullptr; +} + +const OatFile* ClassLinker::GetPrimaryOatFile() { + ReaderMutexLock mu(Thread::Current(), dex_lock_); + const OatFile* boot_oat_file = GetBootOatFile(); + if (boot_oat_file != nullptr) { + for (const OatFile* oat_file : oat_files_) { + if (oat_file != boot_oat_file) { + return oat_file; + } + } + } + return nullptr; +} + // Check for class-def collisions in dex files. // // This works by maintaining a heap with one class from each dex file, sorted by the class @@ -835,18 +863,7 @@ bool ClassLinker::HasCollisions(const OatFile* oat_file, std::string* error_msg) // Add dex files from already loaded oat files, but skip boot. { - // To grab the boot oat, look at the dex files in the boot classpath. Any of those is fine, as - // they were all compiled into the same oat file. So grab the first one, which is guaranteed to - // exist if the boot class-path isn't empty. - const OatFile* boot_oat = nullptr; - if (!boot_class_path_.empty()) { - const DexFile* boot_dex_file = boot_class_path_[0]; - // Is it from an oat file? - if (boot_dex_file->GetOatDexFile() != nullptr) { - boot_oat = boot_dex_file->GetOatDexFile()->GetOatFile(); - } - } - + const OatFile* boot_oat = GetBootOatFile(); for (const OatFile* loaded_oat_file : oat_files_) { if (loaded_oat_file == boot_oat) { continue; diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 57989b272b..95c8aa0244 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -295,6 +295,10 @@ class ClassLinker { return boot_class_path_; } + // Returns the first non-image oat file in the class path. + const OatFile* GetPrimaryOatFile() + LOCKS_EXCLUDED(dex_lock_); + void VisitClasses(ClassVisitor* visitor, void* arg) LOCKS_EXCLUDED(Locks::classlinker_classes_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -615,6 +619,9 @@ class ClassLinker { const OatFile* FindOpenedOatFileFromOatLocation(const std::string& oat_location) LOCKS_EXCLUDED(dex_lock_); + // Returns the boot image oat file. + const OatFile* GetBootOatFile() SHARED_LOCKS_REQUIRED(dex_lock_); + mirror::ArtMethod* CreateProxyConstructor(Thread* self, Handle<mirror::Class> klass, mirror::Class* proxy_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc index f35003864e..99f5d459bb 100644 --- a/runtime/gc/space/image_space.cc +++ b/runtime/gc/space/image_space.cc @@ -203,6 +203,9 @@ static bool GenerateImage(const std::string& image_filename, InstructionSet imag oat_file_option_string += ImageHeader::GetOatLocationFromImageLocation(image_filename); arg_vector.push_back(oat_file_option_string); + // Note: we do not generate a fully debuggable boot image so we do not pass the + // compiler flag --debuggable here. + Runtime::Current()->AddCurrentRuntimeFeaturesAsDex2OatArguments(&arg_vector); CHECK_EQ(image_isa, kRuntimeISA) << "We should always be generating an image for the current isa."; diff --git a/runtime/oat.cc b/runtime/oat.cc index c223e2e0d8..4f6aabc8e5 100644 --- a/runtime/oat.cc +++ b/runtime/oat.cc @@ -27,6 +27,8 @@ namespace art { constexpr uint8_t OatHeader::kOatMagic[4]; constexpr uint8_t OatHeader::kOatVersion[4]; +constexpr const char OatHeader::kTrueValue[]; +constexpr const char OatHeader::kFalseValue[]; static size_t ComputeOatHeaderSize(const SafeMap<std::string, std::string>* variable_data) { size_t estimate = 0U; @@ -443,9 +445,16 @@ size_t OatHeader::GetHeaderSize() const { } bool OatHeader::IsPic() const { - const char* pic_string = GetStoreValueByKey(OatHeader::kPicKey); - static const char kTrue[] = "true"; - return (pic_string != nullptr && strncmp(pic_string, kTrue, sizeof(kTrue)) == 0); + return IsKeyEnabled(OatHeader::kPicKey); +} + +bool OatHeader::IsDebuggable() const { + return IsKeyEnabled(OatHeader::kDebuggableKey); +} + +bool OatHeader::IsKeyEnabled(const char* key) const { + const char* key_value = GetStoreValueByKey(key); + return (key_value != nullptr && strncmp(key_value, kTrueValue, sizeof(kTrueValue)) == 0); } void OatHeader::Flatten(const SafeMap<std::string, std::string>* key_value_store) { diff --git a/runtime/oat.h b/runtime/oat.h index aaf442a77a..604e16171d 100644 --- a/runtime/oat.h +++ b/runtime/oat.h @@ -32,14 +32,18 @@ class InstructionSetFeatures; class PACKED(4) OatHeader { public: static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' }; - static constexpr uint8_t kOatVersion[] = { '0', '6', '2', '\0' }; + static constexpr uint8_t kOatVersion[] = { '0', '6', '3', '\0' }; static constexpr const char* kImageLocationKey = "image-location"; static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline"; static constexpr const char* kDex2OatHostKey = "dex2oat-host"; static constexpr const char* kPicKey = "pic"; + static constexpr const char* kDebuggableKey = "debuggable"; static constexpr const char* kClassPathKey = "classpath"; + static constexpr const char kTrueValue[] = "true"; + static constexpr const char kFalseValue[] = "false"; + static OatHeader* Create(InstructionSet instruction_set, const InstructionSetFeatures* instruction_set_features, const std::vector<const DexFile*>* dex_files, @@ -99,6 +103,7 @@ class PACKED(4) OatHeader { size_t GetHeaderSize() const; bool IsPic() const; + bool IsDebuggable() const; private: OatHeader(InstructionSet instruction_set, @@ -108,6 +113,9 @@ class PACKED(4) OatHeader { uint32_t image_file_location_oat_data_begin, const SafeMap<std::string, std::string>* variable_data); + // Returns true if the value of the given key is "true", false otherwise. + bool IsKeyEnabled(const char* key) const; + void Flatten(const SafeMap<std::string, std::string>* variable_data); uint8_t magic_[4]; diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index b0cbd0e3e2..63ee4b1af0 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -703,6 +703,10 @@ bool OatFile::IsPic() const { // TODO: Check against oat_patches. b/18144996 } +bool OatFile::IsDebuggable() const { + return GetOatHeader().IsDebuggable(); +} + static constexpr char kDexClassPathEncodingSeparator = '*'; std::string OatFile::EncodeDexFileDependencies(const std::vector<const DexFile*>& dex_files) { diff --git a/runtime/oat_file.h b/runtime/oat_file.h index b32dd22490..12e9f6cea7 100644 --- a/runtime/oat_file.h +++ b/runtime/oat_file.h @@ -81,6 +81,9 @@ class OatFile FINAL { bool IsPic() const; + // Indicates whether the oat file was compiled with full debugging capability. + bool IsDebuggable() const; + ElfFile* GetElfFile() const { CHECK_NE(reinterpret_cast<uintptr_t>(elf_file_.get()), reinterpret_cast<uintptr_t>(nullptr)) << "Cannot get an elf file from " << GetLocation(); diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc index d07c09cd9a..d0bfe6eb56 100644 --- a/runtime/oat_file_assistant.cc +++ b/runtime/oat_file_assistant.cc @@ -690,12 +690,20 @@ bool OatFileAssistant::Dex2Oat(const std::vector<std::string>& args, return false; } + ClassLinker* linker = runtime->GetClassLinker(); + CHECK(linker != nullptr) << "ClassLinker is not created yet"; + const OatFile* primary_oat_file = linker->GetPrimaryOatFile(); + const bool debuggable = primary_oat_file != nullptr && primary_oat_file->IsDebuggable(); + std::vector<std::string> argv; argv.push_back(runtime->GetCompilerExecutable()); argv.push_back("--runtime-arg"); argv.push_back("-classpath"); argv.push_back("--runtime-arg"); argv.push_back(runtime->GetClassPathString()); + if (debuggable) { + argv.push_back("--debuggable"); + } runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv); if (!runtime->IsVerificationEnabled()) { diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 2633898b32..2618661ae3 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -1678,10 +1678,6 @@ void Runtime::AddCurrentRuntimeFeaturesAsDex2OatArguments(std::vector<std::strin std::string feature_string("--instruction-set-features="); feature_string += features->GetFeatureString(); argv->push_back(feature_string); - - if (Dbg::IsJdwpConfigured()) { - argv->push_back("--debuggable"); - } } void Runtime::UpdateProfilerState(int state) { |