Merge "Fix debuggable compiler flag detection for secondary dex files" into mnc-dev
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index b4a45c6..3cf458a 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -979,7 +979,10 @@
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 b099088..292f830 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -819,6 +819,34 @@
}
}
+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 @@
// 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 57989b2..95c8aa0 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -295,6 +295,10 @@
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 @@
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 f350038..99f5d45 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -203,6 +203,9 @@
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 c223e2e..4f6aabc 100644
--- a/runtime/oat.cc
+++ b/runtime/oat.cc
@@ -27,6 +27,8 @@
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 @@
}
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 aaf442a..604e161 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,14 +32,18 @@
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 @@
size_t GetHeaderSize() const;
bool IsPic() const;
+ bool IsDebuggable() const;
private:
OatHeader(InstructionSet instruction_set,
@@ -108,6 +113,9 @@
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 b0cbd0e..63ee4b1 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -703,6 +703,10 @@
// 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 b32dd22..12e9f6c 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -81,6 +81,9 @@
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 84d9505..094d8b7 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -690,12 +690,20 @@
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 2633898..2618661 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1678,10 +1678,6 @@
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) {