diff options
Diffstat (limited to 'runtime/debugger.cc')
| -rw-r--r-- | runtime/debugger.cc | 169 |
1 files changed, 117 insertions, 52 deletions
diff --git a/runtime/debugger.cc b/runtime/debugger.cc index cc1e0b994a..6c374029d8 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -1886,11 +1886,25 @@ JDWP::JdwpError Dbg::SetStaticFieldValue(JDWP::FieldId field_id, uint64_t value, return SetFieldValueImpl(0, field_id, value, width, true); } -std::string Dbg::StringToUtf8(JDWP::ObjectId string_id) { +JDWP::JdwpError Dbg::StringToUtf8(JDWP::ObjectId string_id, std::string* str) { JDWP::JdwpError error; - mirror::String* s = gRegistry->Get<mirror::String*>(string_id, &error); - CHECK(s != nullptr) << error; - return s->ToModifiedUtf8(); + mirror::Object* obj = gRegistry->Get<mirror::Object*>(string_id, &error); + if (error != JDWP::ERR_NONE) { + return error; + } + if (obj == nullptr) { + return JDWP::ERR_INVALID_OBJECT; + } + { + ScopedObjectAccessUnchecked soa(Thread::Current()); + mirror::Class* java_lang_String = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_String); + if (!java_lang_String->IsAssignableFrom(obj->GetClass())) { + // This isn't a string. + return JDWP::ERR_INVALID_STRING; + } + } + *str = obj->AsString()->ToModifiedUtf8(); + return JDWP::ERR_NONE; } void Dbg::OutputJValue(JDWP::JdwpTag tag, const JValue* return_value, JDWP::ExpandBuf* pReply) { @@ -1939,7 +1953,7 @@ JDWP::JdwpError Dbg::GetThreadName(JDWP::ObjectId thread_id, std::string* name) } JDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply) { - ScopedObjectAccess soa(Thread::Current()); + ScopedObjectAccessUnchecked soa(Thread::Current()); JDWP::JdwpError error; mirror::Object* thread_object = gRegistry->Get<mirror::Object*>(thread_id, &error); if (error != JDWP::ERR_NONE) { @@ -1970,26 +1984,54 @@ JDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* p return error; } -std::string Dbg::GetThreadGroupName(JDWP::ObjectId thread_group_id) { - ScopedObjectAccess soa(Thread::Current()); +static mirror::Object* DecodeThreadGroup(ScopedObjectAccessUnchecked& soa, + JDWP::ObjectId thread_group_id, JDWP::JdwpError* error) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id, error); + if (*error != JDWP::ERR_NONE) { + return nullptr; + } + if (thread_group == nullptr) { + *error = JDWP::ERR_INVALID_OBJECT; + return nullptr; + } + mirror::Class* c = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ThreadGroup); + CHECK(c != nullptr); + if (!c->IsAssignableFrom(thread_group->GetClass())) { + // This is not a java.lang.ThreadGroup. + *error = JDWP::ERR_INVALID_THREAD_GROUP; + return nullptr; + } + *error = JDWP::ERR_NONE; + return thread_group; +} + +JDWP::JdwpError Dbg::GetThreadGroupName(JDWP::ObjectId thread_group_id, JDWP::ExpandBuf* pReply) { + ScopedObjectAccessUnchecked soa(Thread::Current()); JDWP::JdwpError error; - mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id, &error); - CHECK(thread_group != nullptr) << error; + mirror::Object* thread_group = DecodeThreadGroup(soa, thread_group_id, &error); + if (error != JDWP::ERR_NONE) { + return error; + } const char* old_cause = soa.Self()->StartAssertNoThreadSuspension("Debugger: GetThreadGroupName"); mirror::Class* c = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ThreadGroup); - CHECK(c != nullptr); mirror::ArtField* f = c->FindInstanceField("name", "Ljava/lang/String;"); CHECK(f != nullptr); mirror::String* s = reinterpret_cast<mirror::String*>(f->GetObject(thread_group)); soa.Self()->EndAssertNoThreadSuspension(old_cause); - return s->ToModifiedUtf8(); + + std::string thread_group_name(s->ToModifiedUtf8()); + expandBufAddUtf8String(pReply, thread_group_name); + return JDWP::ERR_NONE; } -JDWP::ObjectId Dbg::GetThreadGroupParent(JDWP::ObjectId thread_group_id) { +JDWP::JdwpError Dbg::GetThreadGroupParent(JDWP::ObjectId thread_group_id, JDWP::ExpandBuf* pReply) { ScopedObjectAccessUnchecked soa(Thread::Current()); JDWP::JdwpError error; - mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id, &error); - CHECK(thread_group != nullptr) << error; + mirror::Object* thread_group = DecodeThreadGroup(soa, thread_group_id, &error); + if (error != JDWP::ERR_NONE) { + return error; + } const char* old_cause = soa.Self()->StartAssertNoThreadSuspension("Debugger: GetThreadGroupParent"); mirror::Class* c = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ThreadGroup); CHECK(c != nullptr); @@ -1997,19 +2039,69 @@ JDWP::ObjectId Dbg::GetThreadGroupParent(JDWP::ObjectId thread_group_id) { CHECK(f != nullptr); mirror::Object* parent = f->GetObject(thread_group); soa.Self()->EndAssertNoThreadSuspension(old_cause); - return gRegistry->Add(parent); + + JDWP::ObjectId parent_group_id = gRegistry->Add(parent); + expandBufAddObjectId(pReply, parent_group_id); + return JDWP::ERR_NONE; } -JDWP::ObjectId Dbg::GetSystemThreadGroupId() { +static void GetChildThreadGroups(ScopedObjectAccessUnchecked& soa, mirror::Object* thread_group, + std::vector<JDWP::ObjectId>* child_thread_group_ids) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + CHECK(thread_group != nullptr); + + // Get the ArrayList<ThreadGroup> "groups" out of this thread group... + mirror::ArtField* groups_field = thread_group->GetClass()->FindInstanceField("groups", "Ljava/util/List;"); + mirror::Object* groups_array_list = groups_field->GetObject(thread_group); + + // Get the array and size out of the ArrayList<ThreadGroup>... + mirror::ArtField* array_field = groups_array_list->GetClass()->FindInstanceField("array", "[Ljava/lang/Object;"); + mirror::ArtField* size_field = groups_array_list->GetClass()->FindInstanceField("size", "I"); + mirror::ObjectArray<mirror::Object>* groups_array = + array_field->GetObject(groups_array_list)->AsObjectArray<mirror::Object>(); + const int32_t size = size_field->GetInt(groups_array_list); + + // Copy the first 'size' elements out of the array into the result. + for (int32_t i = 0; i < size; ++i) { + child_thread_group_ids->push_back(gRegistry->Add(groups_array->Get(i))); + } +} + +JDWP::JdwpError Dbg::GetThreadGroupChildren(JDWP::ObjectId thread_group_id, + JDWP::ExpandBuf* pReply) { ScopedObjectAccessUnchecked soa(Thread::Current()); - mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup); - mirror::Object* group = f->GetObject(f->GetDeclaringClass()); - return gRegistry->Add(group); + JDWP::JdwpError error; + mirror::Object* thread_group = DecodeThreadGroup(soa, thread_group_id, &error); + if (error != JDWP::ERR_NONE) { + return error; + } + + // Add child threads. + { + std::vector<JDWP::ObjectId> child_thread_ids; + GetThreads(thread_group, &child_thread_ids); + expandBufAdd4BE(pReply, child_thread_ids.size()); + for (JDWP::ObjectId child_thread_id : child_thread_ids) { + expandBufAddObjectId(pReply, child_thread_id); + } + } + + // Add child thread groups. + { + std::vector<JDWP::ObjectId> child_thread_groups_ids; + GetChildThreadGroups(soa, thread_group, &child_thread_groups_ids); + expandBufAdd4BE(pReply, child_thread_groups_ids.size()); + for (JDWP::ObjectId child_thread_group_id : child_thread_groups_ids) { + expandBufAddObjectId(pReply, child_thread_group_id); + } + } + + return JDWP::ERR_NONE; } -JDWP::ObjectId Dbg::GetMainThreadGroupId() { - ScopedObjectAccess soa(Thread::Current()); - mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_mainThreadGroup); +JDWP::ObjectId Dbg::GetSystemThreadGroupId() { + ScopedObjectAccessUnchecked soa(Thread::Current()); + mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup); mirror::Object* group = f->GetObject(f->GetDeclaringClass()); return gRegistry->Add(group); } @@ -2111,11 +2203,8 @@ static bool IsInDesiredThreadGroup(ScopedObjectAccessUnchecked& soa, return (group == desired_thread_group); } -void Dbg::GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>* thread_ids) { +void Dbg::GetThreads(mirror::Object* thread_group, std::vector<JDWP::ObjectId>* thread_ids) { ScopedObjectAccessUnchecked soa(Thread::Current()); - JDWP::JdwpError error; - mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id, &error); - CHECK_EQ(error, JDWP::ERR_NONE); std::list<Thread*> all_threads_list; { MutexLock mu(Thread::Current(), *Locks::thread_list_lock_); @@ -2147,30 +2236,6 @@ void Dbg::GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId> } } -void Dbg::GetChildThreadGroups(JDWP::ObjectId thread_group_id, - std::vector<JDWP::ObjectId>* child_thread_group_ids) { - ScopedObjectAccess soa(Thread::Current()); - JDWP::JdwpError error; - mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id, &error); - CHECK(thread_group != nullptr) << error; - - // Get the ArrayList<ThreadGroup> "groups" out of this thread group... - mirror::ArtField* groups_field = thread_group->GetClass()->FindInstanceField("groups", "Ljava/util/List;"); - mirror::Object* groups_array_list = groups_field->GetObject(thread_group); - - // Get the array and size out of the ArrayList<ThreadGroup>... - mirror::ArtField* array_field = groups_array_list->GetClass()->FindInstanceField("array", "[Ljava/lang/Object;"); - mirror::ArtField* size_field = groups_array_list->GetClass()->FindInstanceField("size", "I"); - mirror::ObjectArray<mirror::Object>* groups_array = - array_field->GetObject(groups_array_list)->AsObjectArray<mirror::Object>(); - const int32_t size = size_field->GetInt(groups_array_list); - - // Copy the first 'size' elements out of the array into the result. - for (int32_t i = 0; i < size; ++i) { - child_thread_group_ids->push_back(gRegistry->Add(groups_array->Get(i))); - } -} - static int GetStackDepth(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { struct CountStackDepthVisitor : public StackVisitor { explicit CountStackDepthVisitor(Thread* thread) @@ -4323,7 +4388,7 @@ void Dbg::SetAllocTrackingEnabled(bool enable) { recent_allocation_records_ = new AllocRecord[alloc_record_max_]; CHECK(recent_allocation_records_ != nullptr); } - Runtime::Current()->GetInstrumentation()->InstrumentQuickAllocEntryPoints(); + Runtime::Current()->GetInstrumentation()->InstrumentQuickAllocEntryPoints(false); } else { { ScopedObjectAccess soa(self); // For type_cache_.Clear(); @@ -4339,7 +4404,7 @@ void Dbg::SetAllocTrackingEnabled(bool enable) { type_cache_.Clear(); } // If an allocation comes in before we uninstrument, we will safely drop it on the floor. - Runtime::Current()->GetInstrumentation()->UninstrumentQuickAllocEntryPoints(); + Runtime::Current()->GetInstrumentation()->UninstrumentQuickAllocEntryPoints(false); } } |