summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorSebastien Hertz <shertz@google.com>2015-05-13 12:14:05 +0200
committerSebastien Hertz <shertz@google.com>2015-05-19 19:39:18 +0200
commit094ff2c0c1f736521c634d5f606e274cb6c55345 (patch)
tree9e126be21844e24645120e84e511cbe8f9c33091 /runtime
parentce70082da8a4e63c280c2f049a67b38acc82ee1a (diff)
downloadart-094ff2c0c1f736521c634d5f606e274cb6c55345.zip
art-094ff2c0c1f736521c634d5f606e274cb6c55345.tar.gz
art-094ff2c0c1f736521c634d5f606e274cb6c55345.tar.bz2
Fix debuggable compiler flag detection for secondary dex files
Compiles secondary dex files like the primary dex file: if it has been compiled with the --debuggable flag, compile secondary dex files with the --debuggable flag too. Therefore, dex files loaded at runtime are compiled the same way as dex files compiled at install time on the classpath (excluding the boot image that is not compiled debuggable). Also adds debuggable key in the oat header and bump the oat version. Bug: 20944228 (cherry picked from commit 0de1133ba600f299b3d67938f650720d9f859eb2) Change-Id: If6b2236e7fe547cc421f57b573043748018d3ae0
Diffstat (limited to 'runtime')
-rw-r--r--runtime/class_linker.cc41
-rw-r--r--runtime/class_linker.h7
-rw-r--r--runtime/gc/space/image_space.cc3
-rw-r--r--runtime/oat.cc15
-rw-r--r--runtime/oat.h10
-rw-r--r--runtime/oat_file.cc4
-rw-r--r--runtime/oat_file.h3
-rw-r--r--runtime/oat_file_assistant.cc8
-rw-r--r--runtime/runtime.cc4
9 files changed, 75 insertions, 20 deletions
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 @@ 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 57989b2..95c8aa0 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 f350038..99f5d45 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 c223e2e..4f6aabc 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 aaf442a..604e161 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 b0cbd0e..63ee4b1 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 b32dd22..12e9f6c 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 84d9505..094d8b7 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 2633898..2618661 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) {