diff options
| -rw-r--r-- | runtime/debugger.cc | 17 | ||||
| -rw-r--r-- | runtime/debugger.h | 3 | ||||
| -rw-r--r-- | runtime/dex_file_annotations.cc | 34 | ||||
| -rw-r--r-- | runtime/dex_file_annotations.h | 2 | ||||
| -rw-r--r-- | runtime/jdwp/jdwp_handler.cc | 15 | ||||
| -rwxr-xr-x | tools/run-jdwp-tests.sh | 13 |
6 files changed, 78 insertions, 6 deletions
diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 63794bff6f..d0b50fe820 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -1092,6 +1092,23 @@ JDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId class_id, std::string* signatu return JDWP::ERR_NONE; } +JDWP::JdwpError Dbg::GetSourceDebugExtension(JDWP::RefTypeId class_id, + std::string* extension_data) { + JDWP::JdwpError error; + mirror::Class* c = DecodeClass(class_id, &error); + if (c == nullptr) { + return error; + } + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::Class> klass(hs.NewHandle(c)); + const char* data = annotations::GetSourceDebugExtension(klass); + if (data == nullptr) { + return JDWP::ERR_ABSENT_INFORMATION; + } + *extension_data = data; + return JDWP::ERR_NONE; +} + JDWP::JdwpError Dbg::GetSourceFile(JDWP::RefTypeId class_id, std::string* result) { JDWP::JdwpError error; mirror::Class* c = DecodeClass(class_id, &error); diff --git a/runtime/debugger.h b/runtime/debugger.h index 27124e19fb..4f3ff40e86 100644 --- a/runtime/debugger.h +++ b/runtime/debugger.h @@ -288,6 +288,9 @@ class Dbg { REQUIRES_SHARED(Locks::mutator_lock_); static JDWP::JdwpError GetSignature(JDWP::RefTypeId ref_type_id, std::string* signature) REQUIRES_SHARED(Locks::mutator_lock_); + static JDWP::JdwpError GetSourceDebugExtension(JDWP::RefTypeId ref_type_id, + std::string* extension_data) + REQUIRES_SHARED(Locks::mutator_lock_); static JDWP::JdwpError GetSourceFile(JDWP::RefTypeId ref_type_id, std::string* source_file) REQUIRES_SHARED(Locks::mutator_lock_); static JDWP::JdwpError GetObjectTag(JDWP::ObjectId object_id, uint8_t* tag) diff --git a/runtime/dex_file_annotations.cc b/runtime/dex_file_annotations.cc index 6b9654dc49..7d56bca6ce 100644 --- a/runtime/dex_file_annotations.cc +++ b/runtime/dex_file_annotations.cc @@ -1420,6 +1420,40 @@ mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForClass(Handle<mirro return GetSignatureValue(data, annotation_set); } +const char* GetSourceDebugExtension(Handle<mirror::Class> klass) { + ClassData data(klass); + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data); + if (annotation_set == nullptr) { + return nullptr; + } + const DexFile::AnnotationItem* annotation_item = SearchAnnotationSet( + data.GetDexFile(), + annotation_set, + "Ldalvik/annotation/SourceDebugExtension;", + DexFile::kDexVisibilitySystem); + if (annotation_item == nullptr) { + return nullptr; + } + const uint8_t* annotation = + SearchEncodedAnnotation(data.GetDexFile(), annotation_item->annotation_, "value"); + if (annotation == nullptr) { + return nullptr; + } + DexFile::AnnotationValue annotation_value; + if (!ProcessAnnotationValue<false>(data, + &annotation, + &annotation_value, + ScopedNullHandle<mirror::Class>(), + DexFile::kAllRaw)) { + return nullptr; + } + if (annotation_value.type_ != DexFile::kDexAnnotationString) { + return nullptr; + } + dex::StringIndex index(static_cast<uint32_t>(annotation_value.value_.GetI())); + return data.GetDexFile().StringDataByIdx(index); +} + bool IsClassAnnotationPresent(Handle<mirror::Class> klass, Handle<mirror::Class> annotation_class) { ClassData data(klass); const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data); diff --git a/runtime/dex_file_annotations.h b/runtime/dex_file_annotations.h index c66c5bdb8b..651c9844eb 100644 --- a/runtime/dex_file_annotations.h +++ b/runtime/dex_file_annotations.h @@ -89,6 +89,8 @@ bool GetInnerClassFlags(Handle<mirror::Class> klass, uint32_t* flags) REQUIRES_SHARED(Locks::mutator_lock_); mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForClass(Handle<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_); +const char* GetSourceDebugExtension(Handle<mirror::Class> klass) + REQUIRES_SHARED(Locks::mutator_lock_); bool IsClassAnnotationPresent(Handle<mirror::Class> klass, Handle<mirror::Class> annotation_class) REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/jdwp/jdwp_handler.cc b/runtime/jdwp/jdwp_handler.cc index 971d03958c..e8a9904dc6 100644 --- a/runtime/jdwp/jdwp_handler.cc +++ b/runtime/jdwp/jdwp_handler.cc @@ -335,7 +335,7 @@ static JdwpError VM_CapabilitiesNew(JdwpState*, Request* request, ExpandBuf* rep expandBufAdd1(reply, false); // canUnrestrictedlyRedefineClasses expandBufAdd1(reply, false); // canPopFrames expandBufAdd1(reply, true); // canUseInstanceFilters - expandBufAdd1(reply, false); // canGetSourceDebugExtension + expandBufAdd1(reply, true); // canGetSourceDebugExtension expandBufAdd1(reply, false); // canRequestVMDeathEvent expandBufAdd1(reply, false); // canSetDefaultStratum expandBufAdd1(reply, true); // 1.6: canGetInstanceInfo @@ -499,13 +499,18 @@ static JdwpError RT_ClassObject(JdwpState*, Request* request, ExpandBuf* pReply) /* * Returns the value of the SourceDebugExtension attribute. - * - * JDB seems interested, but DEX files don't currently support this. */ -static JdwpError RT_SourceDebugExtension(JdwpState*, Request*, ExpandBuf*) +static JdwpError RT_SourceDebugExtension(JdwpState*, Request* request, ExpandBuf* pReply) REQUIRES_SHARED(Locks::mutator_lock_) { /* referenceTypeId in, string out */ - return ERR_ABSENT_INFORMATION; + RefTypeId refTypeId = request->ReadRefTypeId(); + std::string extension_data; + JdwpError status = Dbg::GetSourceDebugExtension(refTypeId, &extension_data); + if (status != ERR_NONE) { + return status; + } + expandBufAddUtf8String(pReply, extension_data); + return ERR_NONE; } static JdwpError RT_Signature(JdwpState*, Request* request, ExpandBuf* pReply, bool with_generic) diff --git a/tools/run-jdwp-tests.sh b/tools/run-jdwp-tests.sh index 07c300e7a7..720b1d2f5d 100755 --- a/tools/run-jdwp-tests.sh +++ b/tools/run-jdwp-tests.sh @@ -108,6 +108,17 @@ while true; do fi done +# The JDWP tests include a class with a SourceDebugExtension attribute. Convert this class into +# a DEX so the JDWP SourceDebugExtension can be tested. There is no corresponding java file as by +# definition the class file is generated from a different language. +jsr45_dex=$ANDROID_HOST_OUT/jsr45-test.dex +(cd $ANDROID_BUILD_TOP/external/apache-harmony/jdwp/src/test/resources && + dx --dex --output=$jsr45_dex org/apache/harmony/jpda/tests/jdwp/Events/SourceDebugExtensionMockClass.class ) +if [ $? -ne 0 ]; then + echo Failed to convert class file to DEX. >&2 + exit 1 +fi + # For the host: # # If, on the other hand, there is a variant set, use it to modify the art_debugee parameter to @@ -160,7 +171,7 @@ vogar $vm_command \ --vm-arg -Djpda.settings.waitingTime=$jdwp_test_timeout \ --vm-arg -Djpda.settings.transportAddress=127.0.0.1:55107 \ --vm-arg -Djpda.settings.debuggeeJavaPath="$art_debugee $image $debuggee_args" \ - --classpath $test_jack \ + --classpath $test_jack --resource-classpath $jsr45_dex \ --toolchain jack --language JN \ --vm-arg -Xcompiler-option --vm-arg --debuggable \ --jack-arg -g \ |