debugger.cc revision cb19ebf7609f74b223bd86c94f721498795f9bba
1872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 2872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Copyright (C) 2008 The Android Open Source Project 3872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 4872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 5872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * you may not use this file except in compliance with the License. 6872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * You may obtain a copy of the License at 7872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 8872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 9872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 10872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Unless required by applicable law or agreed to in writing, software 11872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 12872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * See the License for the specific language governing permissions and 14872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * limitations under the License. 15872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 16872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 17872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "debugger.h" 18872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 193bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes#include <sys/uio.h> 203bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes 21545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes#include <set> 22545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 23166db04e259ca51838c311891598664deeed85adIan Rogers#include "arch/context.h" 24545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes#include "class_linker.h" 252dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "class_linker-inl.h" 264f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h" 27776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#include "dex_instruction.h" 281d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/accounting/card_table-inl.h" 291d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/large_object_space.h" 301d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/space-inl.h" 3164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes#include "jdwp/object_registry.h" 32ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_field-inl.h" 33ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h" 342dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class.h" 352dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h" 362dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class_loader.h" 372dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h" 382dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h" 392dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/throwable.h" 406d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h" 4153b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers#include "reflection.h" 42a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes#include "safe_map.h" 4364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes#include "scoped_thread_state_change.h" 446a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes#include "ScopedLocalRef.h" 45f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes#include "ScopedPrimitiveArray.h" 461f5393447b9f45be7918042d9ee7b521376de866Ian Rogers#include "sirt_ref.h" 4747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes#include "stack_indirect_reference_table.h" 48475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes#include "thread_list.h" 4962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include "throw_location.h" 502dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "utf.h" 51eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "well_known_classes.h" 52475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes 533d92d523089bdd7881d2319414a29bf77172b432Brian Carlstrom#ifdef HAVE_ANDROID_OS 543d92d523089bdd7881d2319414a29bf77172b432Brian Carlstrom#include "cutils/properties.h" 553d92d523089bdd7881d2319414a29bf77172b432Brian Carlstrom#endif 563d92d523089bdd7881d2319414a29bf77172b432Brian Carlstrom 57872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace art { 58872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 597934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstromstatic const size_t kMaxAllocRecordStackDepth = 16; // Max 255. 607934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstromstatic const size_t kDefaultNumAllocRecords = 64*1024; // Must be a power of 2. 61475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes 62545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughesstruct AllocRecordStackTraceElement { 63ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* method; 640399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers uint32_t dex_pc; 65545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 66412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier AllocRecordStackTraceElement() : method(nullptr), dex_pc(0) { 67412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier } 68412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier 69b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers int32_t LineNumber() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 700399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers return MethodHelper(method).GetLineNumFromDexPC(dex_pc); 71545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 72545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes}; 73545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 74545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughesstruct AllocRecord { 752dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* type; 76545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes size_t byte_count; 77545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes uint16_t thin_lock_id; 787934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom AllocRecordStackTraceElement stack[kMaxAllocRecordStackDepth]; // Unused entries have NULL method. 79545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 80545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes size_t GetDepth() { 81545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes size_t depth = 0; 82545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes while (depth < kMaxAllocRecordStackDepth && stack[depth].method != NULL) { 83545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes ++depth; 84545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 85545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes return depth; 86545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 87412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier 8883c8ee000d525017ead8753fce6bc1020249b96aMathieu Chartier void UpdateObjectPointers(IsMarkedCallback* callback, void* arg) 89412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 90412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier if (type != nullptr) { 9183c8ee000d525017ead8753fce6bc1020249b96aMathieu Chartier type = down_cast<mirror::Class*>(callback(type, arg)); 92412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier } 93412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier for (size_t stack_frame = 0; stack_frame < kMaxAllocRecordStackDepth; ++stack_frame) { 94412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier mirror::ArtMethod*& m = stack[stack_frame].method; 95412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier if (m == nullptr) { 96412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier break; 97412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier } 9883c8ee000d525017ead8753fce6bc1020249b96aMathieu Chartier m = down_cast<mirror::ArtMethod*>(callback(m, arg)); 99412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier } 100412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier } 101545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes}; 102545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 1038696433d1b3d8ba15288483b777edd888de69135Elliott Hughesstruct Breakpoint { 104ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* method; 105a656a0f6fbcf2ba3f15cae54a773b9c636dd32c1Elliott Hughes uint32_t dex_pc; 106ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom Breakpoint(mirror::ArtMethod* method, uint32_t dex_pc) : method(method), dex_pc(dex_pc) {} 1078696433d1b3d8ba15288483b777edd888de69135Elliott Hughes}; 1088696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 10900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic std::ostream& operator<<(std::ostream& os, const Breakpoint& rhs) 110b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 111229feb7a09317919ee51c06d1c3e715cea25da75Elliott Hughes os << StringPrintf("Breakpoint[%s @%#x]", PrettyMethod(rhs.method).c_str(), rhs.dex_pc); 1128696433d1b3d8ba15288483b777edd888de69135Elliott Hughes return os; 1138696433d1b3d8ba15288483b777edd888de69135Elliott Hughes} 1148696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 11562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersclass DebugInstrumentationListener : public instrumentation::InstrumentationListener { 11662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers public: 11762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers DebugInstrumentationListener() {} 11862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers virtual ~DebugInstrumentationListener() {} 11962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 12062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers virtual void MethodEntered(Thread* thread, mirror::Object* this_object, 121ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::ArtMethod* method, uint32_t dex_pc) 12262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 12362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (method->IsNative()) { 12462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // TODO: post location events is a suspension point and native method entry stubs aren't. 12562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return; 12662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 127579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao Dbg::PostLocationEvent(method, 0, this_object, Dbg::kMethodEntry, nullptr); 12862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 12962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 13062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers virtual void MethodExited(Thread* thread, mirror::Object* this_object, 131ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::ArtMethod* method, 13262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers uint32_t dex_pc, const JValue& return_value) 13362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 13462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (method->IsNative()) { 13562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // TODO: post location events is a suspension point and native method entry stubs aren't. 13662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return; 13762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 138579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao Dbg::PostLocationEvent(method, dex_pc, this_object, Dbg::kMethodExit, &return_value); 13962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 14062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 14151db44a194bafc3810a41164a8b39614f10e79dfSebastien Hertz virtual void MethodUnwind(Thread* thread, mirror::Object* this_object, 142ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::ArtMethod* method, uint32_t dex_pc) 14351db44a194bafc3810a41164a8b39614f10e79dfSebastien Hertz SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 14462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // We're not recorded to listen to this kind of event, so complain. 14562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LOG(ERROR) << "Unexpected method unwind event in debugger " << PrettyMethod(method) 14651db44a194bafc3810a41164a8b39614f10e79dfSebastien Hertz << " " << dex_pc; 14762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 14862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 14962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers virtual void DexPcMoved(Thread* thread, mirror::Object* this_object, 150ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::ArtMethod* method, uint32_t new_dex_pc) 15162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 15262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Dbg::UpdateDebugger(thread, this_object, method, new_dex_pc); 15362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 15462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 15562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers virtual void ExceptionCaught(Thread* thread, const ThrowLocation& throw_location, 156ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* catch_method, uint32_t catch_dex_pc, 15762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers mirror::Throwable* exception_object) 15862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 15962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Dbg::PostException(thread, throw_location, catch_method, catch_dex_pc, exception_object); 16062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 16162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} gDebugInstrumentationListener; 16262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 1634ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughes// JDWP is allowed unless the Zygote forbids it. 1644ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughesstatic bool gJdwpAllowed = true; 1654ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughes 166c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes// Was there a -Xrunjdwp or -agentlib:jdwp= argument on the command line? 1673bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughesstatic bool gJdwpConfigured = false; 1683bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes 169c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes// Broken-down JDWP options. (Only valid if IsJdwpConfigured() is true.) 170376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesstatic JDWP::JdwpOptions gJdwpOptions; 1713bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes 1723bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes// Runtime JDWP state. 1733bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughesstatic JDWP::JdwpState* gJdwpState = NULL; 1743bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughesstatic bool gDebuggerConnected; // debugger or DDMS is connected. 1753bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughesstatic bool gDebuggerActive; // debugger is making requests. 1768696433d1b3d8ba15288483b777edd888de69135Elliott Hughesstatic bool gDisposed; // debugger called VirtualMachine.Dispose, so we should drop the connection. 1773bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes 17847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughesstatic bool gDdmThreadNotification = false; 17947fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 180767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes// DDMS GC-related settings. 181767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesstatic Dbg::HpifWhen gDdmHpifWhen = Dbg::HPIF_WHEN_NEVER; 182767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesstatic Dbg::HpsgWhen gDdmHpsgWhen = Dbg::HPSG_WHEN_NEVER; 183767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesstatic Dbg::HpsgWhat gDdmHpsgWhat; 184767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesstatic Dbg::HpsgWhen gDdmNhsgWhen = Dbg::HPSG_WHEN_NEVER; 185767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesstatic Dbg::HpsgWhat gDdmNhsgWhat; 186767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 187719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogersstatic ObjectRegistry* gRegistry = nullptr; 188475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes 189545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes// Recent allocation tracking. 190719d1a33f6569864f529e5a3fff59e7bca97aad0Ian RogersMutex* Dbg::alloc_tracker_lock_ = nullptr; 191719d1a33f6569864f529e5a3fff59e7bca97aad0Ian RogersAllocRecord* Dbg::recent_allocation_records_ = nullptr; // TODO: CircularBuffer<AllocRecord> 192719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogerssize_t Dbg::alloc_record_max_ = 0; 193719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogerssize_t Dbg::alloc_record_head_ = 0; 194719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogerssize_t Dbg::alloc_record_count_ = 0; 195545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 196138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz// Deoptimization support. 197138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertzstruct MethodInstrumentationRequest { 198138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz bool deoptimize; 199138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 200138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz // Method for selective deoptimization. NULL means full deoptimization. 201138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz mirror::ArtMethod* method; 202138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 203138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz MethodInstrumentationRequest(bool deoptimize, mirror::ArtMethod* method) 204138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz : deoptimize(deoptimize), method(method) {} 205138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz}; 206138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz// TODO we need to visit associated methods as roots. 207138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertzstatic std::vector<MethodInstrumentationRequest> gDeoptimizationRequests GUARDED_BY(Locks::deoptimization_lock_); 208138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 209138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz// Breakpoints. 21009bfc6a50bdc9366b13ac3ab479d9278c853d90ajeffhaostatic std::vector<Breakpoint> gBreakpoints GUARDED_BY(Locks::breakpoint_lock_); 2118696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 212ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromstatic bool IsBreakpoint(const mirror::ArtMethod* m, uint32_t dex_pc) 21309bfc6a50bdc9366b13ac3ab479d9278c853d90ajeffhao LOCKS_EXCLUDED(Locks::breakpoint_lock_) 214b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 21509bfc6a50bdc9366b13ac3ab479d9278c853d90ajeffhao MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_); 216138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz for (size_t i = 0, e = gBreakpoints.size(); i < e; ++i) { 217a656a0f6fbcf2ba3f15cae54a773b9c636dd32c1Elliott Hughes if (gBreakpoints[i].method == m && gBreakpoints[i].dex_pc == dex_pc) { 2188696433d1b3d8ba15288483b777edd888de69135Elliott Hughes VLOG(jdwp) << "Hit breakpoint #" << i << ": " << gBreakpoints[i]; 2198696433d1b3d8ba15288483b777edd888de69135Elliott Hughes return true; 2208696433d1b3d8ba15288483b777edd888de69135Elliott Hughes } 2218696433d1b3d8ba15288483b777edd888de69135Elliott Hughes } 2228696433d1b3d8ba15288483b777edd888de69135Elliott Hughes return false; 2238696433d1b3d8ba15288483b777edd888de69135Elliott Hughes} 2248696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 22552d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertzstatic bool IsSuspendedForDebugger(ScopedObjectAccessUnchecked& soa, Thread* thread) 22652d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) { 2279e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes MutexLock mu(soa.Self(), *Locks::thread_suspend_count_lock_); 2289e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes // A thread may be suspended for GC; in this code, we really want to know whether 2299e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes // there's a debugger suspension active. 2309e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes return thread->IsSuspended() && thread->GetDebugSuspendCount() > 0; 2319e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes} 2329e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes 2332dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersstatic mirror::Array* DecodeArray(JDWP::RefTypeId id, JDWP::JdwpError& status) 234b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 2352dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(id); 23664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (o == NULL || o == ObjectRegistry::kInvalidObject) { 237436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes status = JDWP::ERR_INVALID_OBJECT; 238436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return NULL; 239436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes } 240436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes if (!o->IsArrayInstance()) { 241436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes status = JDWP::ERR_INVALID_ARRAY; 242436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return NULL; 243436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes } 244436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes status = JDWP::ERR_NONE; 245436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return o->AsArray(); 246436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes} 247436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes 2482dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersstatic mirror::Class* DecodeClass(JDWP::RefTypeId id, JDWP::JdwpError& status) 249b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 2502dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(id); 25164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (o == NULL || o == ObjectRegistry::kInvalidObject) { 252436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes status = JDWP::ERR_INVALID_OBJECT; 253436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return NULL; 254436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes } 255436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes if (!o->IsClass()) { 256436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes status = JDWP::ERR_INVALID_CLASS; 257436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return NULL; 258436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes } 259436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes status = JDWP::ERR_NONE; 260436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return o->AsClass(); 261436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes} 262436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes 263221229cb523f849f165fdafbf9785010963715daElliott Hughesstatic JDWP::JdwpError DecodeThread(ScopedObjectAccessUnchecked& soa, JDWP::ObjectId thread_id, Thread*& thread) 264a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao EXCLUSIVE_LOCKS_REQUIRED(Locks::thread_list_lock_) 265b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) 266b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 2672dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* thread_peer = gRegistry->Get<mirror::Object*>(thread_id); 26864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (thread_peer == NULL || thread_peer == ObjectRegistry::kInvalidObject) { 269221229cb523f849f165fdafbf9785010963715daElliott Hughes // This isn't even an object. 270221229cb523f849f165fdafbf9785010963715daElliott Hughes return JDWP::ERR_INVALID_OBJECT; 271221229cb523f849f165fdafbf9785010963715daElliott Hughes } 272221229cb523f849f165fdafbf9785010963715daElliott Hughes 2732dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* java_lang_Thread = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread); 274221229cb523f849f165fdafbf9785010963715daElliott Hughes if (!java_lang_Thread->IsAssignableFrom(thread_peer->GetClass())) { 275221229cb523f849f165fdafbf9785010963715daElliott Hughes // This isn't a thread. 276221229cb523f849f165fdafbf9785010963715daElliott Hughes return JDWP::ERR_INVALID_THREAD; 277221229cb523f849f165fdafbf9785010963715daElliott Hughes } 278221229cb523f849f165fdafbf9785010963715daElliott Hughes 279221229cb523f849f165fdafbf9785010963715daElliott Hughes thread = Thread::FromManagedThread(soa, thread_peer); 280221229cb523f849f165fdafbf9785010963715daElliott Hughes if (thread == NULL) { 281221229cb523f849f165fdafbf9785010963715daElliott Hughes // This is a java.lang.Thread without a Thread*. Must be a zombie. 282221229cb523f849f165fdafbf9785010963715daElliott Hughes return JDWP::ERR_THREAD_NOT_ALIVE; 283436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes } 284221229cb523f849f165fdafbf9785010963715daElliott Hughes return JDWP::ERR_NONE; 285436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes} 286436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes 28724437995cdac88b42e42b16d9aa121e833330999Elliott Hughesstatic JDWP::JdwpTag BasicTagFromDescriptor(const char* descriptor) { 28824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes // JDWP deliberately uses the descriptor characters' ASCII values for its enum. 28924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes // Note that by "basic" we mean that we don't get more specific than JT_OBJECT. 29024437995cdac88b42e42b16d9aa121e833330999Elliott Hughes return static_cast<JDWP::JdwpTag>(descriptor[0]); 29124437995cdac88b42e42b16d9aa121e833330999Elliott Hughes} 29224437995cdac88b42e42b16d9aa121e833330999Elliott Hughes 2939837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogersstatic JDWP::JdwpTag TagFromClass(const ScopedObjectAccessUnchecked& soa, mirror::Class* c) 294b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 29586b0010c79ef95b5333cd540b7d3af34a9f1a643Elliott Hughes CHECK(c != NULL); 29624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes if (c->IsArrayClass()) { 29724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes return JDWP::JT_ARRAY; 29824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } 29924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes if (c->IsStringClass()) { 30024437995cdac88b42e42b16d9aa121e833330999Elliott Hughes return JDWP::JT_STRING; 3019837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers } 3029837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers if (c->IsClassClass()) { 30324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes return JDWP::JT_CLASS_OBJECT; 30424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } 3059837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers { 3069837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers mirror::Class* thread_class = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread); 3079837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers if (thread_class->IsAssignableFrom(c)) { 3089837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers return JDWP::JT_THREAD; 3099837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers } 3109837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers } 3119837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers { 3129837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers mirror::Class* thread_group_class = 3139837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ThreadGroup); 3149837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers if (thread_group_class->IsAssignableFrom(c)) { 3159837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers return JDWP::JT_THREAD_GROUP; 3169837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers } 3179837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers } 3189837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers { 3199837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers mirror::Class* class_loader_class = 3209837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ClassLoader); 3219837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers if (class_loader_class->IsAssignableFrom(c)) { 3229837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers return JDWP::JT_CLASS_LOADER; 3239837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers } 3249837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers } 3259837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers return JDWP::JT_OBJECT; 32624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes} 32724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes 32824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes/* 32924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes * Objects declared to hold Object might actually hold a more specific 33024437995cdac88b42e42b16d9aa121e833330999Elliott Hughes * type. The debugger may take a special interest in these (e.g. it 33124437995cdac88b42e42b16d9aa121e833330999Elliott Hughes * wants to display the contents of Strings), so we want to return an 33224437995cdac88b42e42b16d9aa121e833330999Elliott Hughes * appropriate tag. 33324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes * 33424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes * Null objects are tagged JT_OBJECT. 33524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes */ 3369837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogersstatic JDWP::JdwpTag TagFromObject(const ScopedObjectAccessUnchecked& soa, mirror::Object* o) 337b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 3389837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers return (o == NULL) ? JDWP::JT_OBJECT : TagFromClass(soa, o->GetClass()); 33924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes} 34024437995cdac88b42e42b16d9aa121e833330999Elliott Hughes 34124437995cdac88b42e42b16d9aa121e833330999Elliott Hughesstatic bool IsPrimitiveTag(JDWP::JdwpTag tag) { 34224437995cdac88b42e42b16d9aa121e833330999Elliott Hughes switch (tag) { 34324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes case JDWP::JT_BOOLEAN: 34424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes case JDWP::JT_BYTE: 34524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes case JDWP::JT_CHAR: 34624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes case JDWP::JT_FLOAT: 34724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes case JDWP::JT_DOUBLE: 34824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes case JDWP::JT_INT: 34924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes case JDWP::JT_LONG: 35024437995cdac88b42e42b16d9aa121e833330999Elliott Hughes case JDWP::JT_SHORT: 35124437995cdac88b42e42b16d9aa121e833330999Elliott Hughes case JDWP::JT_VOID: 35224437995cdac88b42e42b16d9aa121e833330999Elliott Hughes return true; 35324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes default: 35424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes return false; 35524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } 35624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes} 35724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes 3583bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes/* 3593bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes * Handle one of the JDWP name/value pairs. 3603bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes * 3613bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes * JDWP options are: 3623bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes * help: if specified, show help message and bail 3633bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes * transport: may be dt_socket or dt_shmem 3643bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes * address: for dt_socket, "host:port", or just "port" when listening 3653bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes * server: if "y", wait for debugger to attach; if "n", attach to debugger 3663bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes * timeout: how long to wait for debugger to connect / listen 3673bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes * 3683bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes * Useful with server=n (these aren't supported yet): 3693bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes * onthrow=<exception-name>: connect to debugger when exception thrown 3703bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes * onuncaught=y|n: connect to debugger when uncaught exception thrown 3713bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes * launch=<command-line>: launch the debugger itself 3723bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes * 3733bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes * The "transport" option is required, as is "address" if server=n. 3743bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes */ 3753bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughesstatic bool ParseJdwpOption(const std::string& name, const std::string& value) { 3763bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes if (name == "transport") { 3773bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes if (value == "dt_socket") { 378376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes gJdwpOptions.transport = JDWP::kJdwpTransportSocket; 3793bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } else if (value == "dt_android_adb") { 380376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes gJdwpOptions.transport = JDWP::kJdwpTransportAndroidAdb; 3813bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } else { 3823bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes LOG(ERROR) << "JDWP transport not supported: " << value; 3833bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes return false; 3843bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } 3853bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } else if (name == "server") { 3863bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes if (value == "n") { 387376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes gJdwpOptions.server = false; 3883bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } else if (value == "y") { 389376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes gJdwpOptions.server = true; 3903bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } else { 3913bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes LOG(ERROR) << "JDWP option 'server' must be 'y' or 'n'"; 3923bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes return false; 3933bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } 3943bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } else if (name == "suspend") { 3953bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes if (value == "n") { 396376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes gJdwpOptions.suspend = false; 3973bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } else if (value == "y") { 398376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes gJdwpOptions.suspend = true; 3993bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } else { 4003bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes LOG(ERROR) << "JDWP option 'suspend' must be 'y' or 'n'"; 4013bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes return false; 4023bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } 4033bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } else if (name == "address") { 4043bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes /* this is either <port> or <host>:<port> */ 4053bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes std::string port_string; 406376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes gJdwpOptions.host.clear(); 4073bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes std::string::size_type colon = value.find(':'); 4083bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes if (colon != std::string::npos) { 409376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes gJdwpOptions.host = value.substr(0, colon); 4103bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes port_string = value.substr(colon + 1); 4113bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } else { 4123bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes port_string = value; 4133bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } 4143bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes if (port_string.empty()) { 4153bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes LOG(ERROR) << "JDWP address missing port: " << value; 4163bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes return false; 4173bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } 4183bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes char* end; 419ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes uint64_t port = strtoul(port_string.c_str(), &end, 10); 420ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes if (*end != '\0' || port > 0xffff) { 4213bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes LOG(ERROR) << "JDWP address has junk in port field: " << value; 4223bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes return false; 4233bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } 424376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes gJdwpOptions.port = port; 4253bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } else if (name == "launch" || name == "onthrow" || name == "oncaught" || name == "timeout") { 4263bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes /* valid but unsupported */ 4273bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes LOG(INFO) << "Ignoring JDWP option '" << name << "'='" << value << "'"; 4283bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } else { 4293bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes LOG(INFO) << "Ignoring unrecognized JDWP option '" << name << "'='" << value << "'"; 4303bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } 4313bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes 4323bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes return true; 4333bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes} 4343bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes 4353bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes/* 4363bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes * Parse the latter half of a -Xrunjdwp/-agentlib:jdwp= string, e.g.: 4373bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes * "transport=dt_socket,address=8000,server=y,suspend=n" 4383bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes */ 4393bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughesbool Dbg::ParseJdwpOptions(const std::string& options) { 4404dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << "ParseJdwpOptions: " << options; 44147fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 4423bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes std::vector<std::string> pairs; 4433bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes Split(options, ',', pairs); 4443bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes 4453bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes for (size_t i = 0; i < pairs.size(); ++i) { 4463bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes std::string::size_type equals = pairs[i].find('='); 4473bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes if (equals == std::string::npos) { 4483bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes LOG(ERROR) << "Can't parse JDWP option '" << pairs[i] << "' in '" << options << "'"; 4493bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes return false; 4503bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } 4513bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes ParseJdwpOption(pairs[i].substr(0, equals), pairs[i].substr(equals + 1)); 4523bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } 4533bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes 454376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes if (gJdwpOptions.transport == JDWP::kJdwpTransportUnknown) { 4553bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes LOG(ERROR) << "Must specify JDWP transport: " << options; 4563bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } 457376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes if (!gJdwpOptions.server && (gJdwpOptions.host.empty() || gJdwpOptions.port == 0)) { 4583bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes LOG(ERROR) << "Must specify JDWP host and port when server=n: " << options; 4593bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes return false; 4603bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } 4613bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes 4623bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes gJdwpConfigured = true; 4633bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes return true; 4643bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes} 4653bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes 466d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughesvoid Dbg::StartJdwp() { 467c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes if (!gJdwpAllowed || !IsJdwpConfigured()) { 468376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes // No JDWP for you! 469376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes return; 470376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes } 471376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes 472719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers CHECK(gRegistry == nullptr); 473475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes gRegistry = new ObjectRegistry; 474475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes 475719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers alloc_tracker_lock_ = new Mutex("AllocTracker lock"); 476d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes // Init JDWP if the debugger is enabled. This may connect out to a 477d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes // debugger, passively listen for a debugger, or block waiting for a 478d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes // debugger. 479376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes gJdwpState = JDWP::JdwpState::Create(&gJdwpOptions); 480376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes if (gJdwpState == NULL) { 481f8a2df7bbf1021058bc13d1f806a7fec3c89ee62Elliott Hughes // We probably failed because some other process has the port already, which means that 482f8a2df7bbf1021058bc13d1f806a7fec3c89ee62Elliott Hughes // if we don't abort the user is likely to think they're talking to us when they're actually 483f8a2df7bbf1021058bc13d1f806a7fec3c89ee62Elliott Hughes // talking to that other process. 4843d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes LOG(FATAL) << "Debugger thread failed to initialize"; 485d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes } 486d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes 487d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes // If a debugger has already attached, send the "welcome" message. 488d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes // This may cause us to suspend all threads. 489376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes if (gJdwpState->IsActive()) { 49000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 491376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes if (!gJdwpState->PostVMStart()) { 4923d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes LOG(WARNING) << "Failed to post 'start' message to debugger"; 493d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes } 494d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes } 495872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 496872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 497d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughesvoid Dbg::StopJdwp() { 4980376e6b62bfb43b515b791f0a7afed2d0d8030bcSebastien Hertz // Prevent the JDWP thread from processing JDWP incoming packets after we close the connection. 4990376e6b62bfb43b515b791f0a7afed2d0d8030bcSebastien Hertz Disposed(); 500376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes delete gJdwpState; 501719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers gJdwpState = nullptr; 502475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes delete gRegistry; 503719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers gRegistry = nullptr; 504719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers delete alloc_tracker_lock_; 505719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers alloc_tracker_lock_ = nullptr; 506872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 507872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 508767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesvoid Dbg::GcDidFinish() { 509767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes if (gDdmHpifWhen != HPIF_WHEN_NEVER) { 51000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 51181ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes LOG(DEBUG) << "Sending heap info to DDM"; 5127162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes DdmSendHeapInfo(gDdmHpifWhen); 513767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } 514767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes if (gDdmHpsgWhen != HPSG_WHEN_NEVER) { 51500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 51681ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes LOG(DEBUG) << "Dumping heap to DDM"; 5176a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes DdmSendHeapSegments(false); 518767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } 519767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes if (gDdmNhsgWhen != HPSG_WHEN_NEVER) { 52000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 521767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes LOG(DEBUG) << "Dumping native heap to DDM"; 5226a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes DdmSendHeapSegments(true); 523767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } 524767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes} 525767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 5264ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughesvoid Dbg::SetJdwpAllowed(bool allowed) { 5274ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughes gJdwpAllowed = allowed; 5284ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughes} 5294ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughes 530872d4ec7225444d9400d30f9027247deb91012fdElliott HughesDebugInvokeReq* Dbg::GetInvokeReq() { 531475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes return Thread::Current()->GetInvokeReq(); 532475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes} 533475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes 534475fc23a4a7f35d1be87ea0b06c80df317a720acElliott HughesThread* Dbg::GetDebugThread() { 535475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes return (gJdwpState != NULL) ? gJdwpState->GetDebugThread() : NULL; 536475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes} 537475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes 538475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughesvoid Dbg::ClearWaitForEventThread() { 539475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes gJdwpState->ClearWaitForEventThread(); 540872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 541872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 542872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::Connected() { 5433bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes CHECK(!gDebuggerConnected); 5444dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << "JDWP has attached"; 5453bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes gDebuggerConnected = true; 5468696433d1b3d8ba15288483b777edd888de69135Elliott Hughes gDisposed = false; 5478696433d1b3d8ba15288483b777edd888de69135Elliott Hughes} 5488696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 5498696433d1b3d8ba15288483b777edd888de69135Elliott Hughesvoid Dbg::Disposed() { 5508696433d1b3d8ba15288483b777edd888de69135Elliott Hughes gDisposed = true; 5518696433d1b3d8ba15288483b777edd888de69135Elliott Hughes} 5528696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 5538696433d1b3d8ba15288483b777edd888de69135Elliott Hughesbool Dbg::IsDisposed() { 5548696433d1b3d8ba15288483b777edd888de69135Elliott Hughes return gDisposed; 555872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 556872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 557a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughesvoid Dbg::GoActive() { 558a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // Enable all debugging features, including scans for breakpoints. 559a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // This is a no-op if we're already active. 560a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // Only called from the JDWP handler thread. 561a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes if (gDebuggerActive) { 562a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return; 563a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 564a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 565c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes { 566c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes // TODO: dalvik only warned if there were breakpoints left over. clear in Dbg::Disconnected? 56709bfc6a50bdc9366b13ac3ab479d9278c853d90ajeffhao MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_); 568c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes CHECK_EQ(gBreakpoints.size(), 0U); 569c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes } 570a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 571138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz { 572138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_); 573138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz CHECK_EQ(gDeoptimizationRequests.size(), 0U); 574138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 575138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 57662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Runtime* runtime = Runtime::Current(); 57762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers runtime->GetThreadList()->SuspendAll(); 57862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Thread* self = Thread::Current(); 57962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThreadState old_state = self->SetStateUnsafe(kRunnable); 58062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers CHECK_NE(old_state, kRunnable); 581138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz runtime->GetInstrumentation()->EnableDeoptimization(); 58262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers runtime->GetInstrumentation()->AddListener(&gDebugInstrumentationListener, 58362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers instrumentation::Instrumentation::kMethodEntered | 58462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers instrumentation::Instrumentation::kMethodExited | 58514dd5a82ad85a28612bf86e755ff929d767cea4cJeff Hao instrumentation::Instrumentation::kDexPcMoved | 58614dd5a82ad85a28612bf86e755ff929d767cea4cJeff Hao instrumentation::Instrumentation::kExceptionCaught); 587a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes gDebuggerActive = true; 58862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers CHECK_EQ(self->SetStateUnsafe(old_state), kRunnable); 58962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers runtime->GetThreadList()->ResumeAll(); 59062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 59162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LOG(INFO) << "Debugger is active"; 592872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 593872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 594872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::Disconnected() { 595234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes CHECK(gDebuggerConnected); 596234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes 597c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes LOG(INFO) << "Debugger is no longer active"; 598234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes 59962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // Suspend all threads and exclusively acquire the mutator lock. Set the state of the thread 60062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // to kRunnable to avoid scoped object access transitions. Remove the debugger as a listener 60162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // and clear the object registry. 60262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Runtime* runtime = Runtime::Current(); 60362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers runtime->GetThreadList()->SuspendAll(); 60462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Thread* self = Thread::Current(); 60562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThreadState old_state = self->SetStateUnsafe(kRunnable); 606aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz 607aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz // Debugger may not be active at this point. 608aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz if (gDebuggerActive) { 609aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz { 610aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz // Since we're going to disable deoptimization, we clear the deoptimization requests queue. 611aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz // This prevents us from having any pending deoptimization request when the debugger attaches 612aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz // to us again while no event has been requested yet. 613aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_); 614aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz gDeoptimizationRequests.clear(); 615aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz } 616aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz runtime->GetInstrumentation()->RemoveListener(&gDebugInstrumentationListener, 617aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz instrumentation::Instrumentation::kMethodEntered | 618aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz instrumentation::Instrumentation::kMethodExited | 619aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz instrumentation::Instrumentation::kDexPcMoved | 620aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz instrumentation::Instrumentation::kExceptionCaught); 621aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz runtime->GetInstrumentation()->DisableDeoptimization(); 622aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz gDebuggerActive = false; 623aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz } 624234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes gRegistry->Clear(); 625234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes gDebuggerConnected = false; 62662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers CHECK_EQ(self->SetStateUnsafe(old_state), kRunnable); 62762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers runtime->GetThreadList()->ResumeAll(); 628872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 629872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 630c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughesbool Dbg::IsDebuggerActive() { 6313bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes return gDebuggerActive; 632872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 633872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 634c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughesbool Dbg::IsJdwpConfigured() { 6353bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes return gJdwpConfigured; 636872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 637872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 638872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesint64_t Dbg::LastDebuggerActivity() { 639ca9515205010099d006ac2fac244348a1e673dcbElliott Hughes return gJdwpState->LastDebuggerActivity(); 640872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 641872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 642872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::UndoDebuggerSuspensions() { 643234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes Runtime::Current()->GetThreadList()->UndoDebuggerSuspensions(); 644872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 645872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 64688d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughesstd::string Dbg::GetClassName(JDWP::RefTypeId class_id) { 6472dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(class_id); 6483d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes if (o == NULL) { 649436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return "NULL"; 6507b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 65164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (o == ObjectRegistry::kInvalidObject) { 65288d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes return StringPrintf("invalid object %p", reinterpret_cast<void*>(class_id)); 6533d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes } 6543d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes if (!o->IsClass()) { 6557934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom return StringPrintf("non-class %p", o); // This is only used for debugging output anyway. 6563d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes } 657436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return DescriptorToName(ClassHelper(o->AsClass()).GetDescriptor()); 6583d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes} 6593d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes 66088d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId& class_object_id) { 661436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes JDWP::JdwpError status; 6622dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = DecodeClass(id, status); 663436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes if (c == NULL) { 664436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return status; 6652435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 66688d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes class_object_id = gRegistry->Add(c); 667436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 6688696433d1b3d8ba15288483b777edd888de69135Elliott Hughes} 6698696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 67088d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId& superclass_id) { 6713d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes JDWP::JdwpError status; 6722dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = DecodeClass(id, status); 6733d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes if (c == NULL) { 6743d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return status; 6753d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes } 6763d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes if (c->IsInterface()) { 6773d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes // http://code.google.com/p/android/issues/detail?id=20856 67888d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes superclass_id = 0; 6793d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes } else { 68088d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes superclass_id = gRegistry->Add(c->GetSuperClass()); 6813d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes } 6823d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return JDWP::ERR_NONE; 683872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 684872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 685436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott HughesJDWP::JdwpError Dbg::GetClassLoader(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) { 6862dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(id); 68764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (o == NULL || o == ObjectRegistry::kInvalidObject) { 688436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 689436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes } 690436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes expandBufAddObjectId(pReply, gRegistry->Add(o->GetClass()->GetClassLoader())); 691436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 692872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 693872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 694436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott HughesJDWP::JdwpError Dbg::GetModifiers(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) { 695436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes JDWP::JdwpError status; 6962dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = DecodeClass(id, status); 697436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes if (c == NULL) { 698436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return status; 6997b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 700436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes 701436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes uint32_t access_flags = c->GetAccessFlags() & kAccJavaFlagsMask; 702436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes 703de34eea060edb4eb34d6ecd840e6e1c4c6489642Yevgeny Rouban // Set ACC_SUPER. Dex files don't contain this flag but only classes are supposed to have it set, 704de34eea060edb4eb34d6ecd840e6e1c4c6489642Yevgeny Rouban // not interfaces. 705436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes // Class.getModifiers doesn't return it, but JDWP does, so we set it here. 706de34eea060edb4eb34d6ecd840e6e1c4c6489642Yevgeny Rouban if ((access_flags & kAccInterface) == 0) { 707de34eea060edb4eb34d6ecd840e6e1c4c6489642Yevgeny Rouban access_flags |= kAccSuper; 708de34eea060edb4eb34d6ecd840e6e1c4c6489642Yevgeny Rouban } 709436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes 710436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes expandBufAdd4BE(pReply, access_flags); 711436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes 712436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 713872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 714872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 715f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott HughesJDWP::JdwpError Dbg::GetMonitorInfo(JDWP::ObjectId object_id, JDWP::ExpandBuf* reply) 716f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 7172dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); 71864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (o == NULL || o == ObjectRegistry::kInvalidObject) { 719f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 720f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes } 721f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes 722f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes // Ensure all threads are suspended while we read objects' lock words. 723f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes Thread* self = Thread::Current(); 724f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes Locks::mutator_lock_->SharedUnlock(self); 725f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes Locks::mutator_lock_->ExclusiveLock(self); 726f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes 727f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes MonitorInfo monitor_info(o); 728f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes 729f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes Locks::mutator_lock_->ExclusiveUnlock(self); 730f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes Locks::mutator_lock_->SharedLock(self); 731f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes 732d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers if (monitor_info.owner_ != NULL) { 733d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers expandBufAddObjectId(reply, gRegistry->Add(monitor_info.owner_->GetPeer())); 734f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes } else { 735f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes expandBufAddObjectId(reply, gRegistry->Add(NULL)); 736f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes } 737d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers expandBufAdd4BE(reply, monitor_info.entry_count_); 738d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers expandBufAdd4BE(reply, monitor_info.waiters_.size()); 739d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers for (size_t i = 0; i < monitor_info.waiters_.size(); ++i) { 740d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers expandBufAddObjectId(reply, gRegistry->Add(monitor_info.waiters_[i]->GetPeer())); 741f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes } 742f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes return JDWP::ERR_NONE; 743f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes} 744f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes 745734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott HughesJDWP::JdwpError Dbg::GetOwnedMonitors(JDWP::ObjectId thread_id, 746734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes std::vector<JDWP::ObjectId>& monitors, 74752d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz std::vector<uint32_t>& stack_depths) { 7484993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes ScopedObjectAccessUnchecked soa(Thread::Current()); 7494993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 7504993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes Thread* thread; 7514993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); 7524993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes if (error != JDWP::ERR_NONE) { 7534993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes return error; 7544993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes } 7554993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes if (!IsSuspendedForDebugger(soa, thread)) { 7564993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes return JDWP::ERR_THREAD_NOT_SUSPENDED; 7574993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes } 7584993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes 7594993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes struct OwnedMonitorVisitor : public StackVisitor { 7607a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers OwnedMonitorVisitor(Thread* thread, Context* context) 7614993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 7627a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers : StackVisitor(thread, context), current_stack_depth(0) {} 7634993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes 7644993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses 7654993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes // annotalysis. 7664993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { 7674993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes if (!GetMethod()->IsRuntimeMethod()) { 7684993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes Monitor::VisitLocks(this, AppendOwnedMonitors, this); 769734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes ++current_stack_depth; 7704993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes } 7714993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes return true; 7724993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes } 7734993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes 7742dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers static void AppendOwnedMonitors(mirror::Object* owned_monitor, void* arg) { 7757a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers OwnedMonitorVisitor* visitor = reinterpret_cast<OwnedMonitorVisitor*>(arg); 776734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes visitor->monitors.push_back(owned_monitor); 777734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes visitor->stack_depths.push_back(visitor->current_stack_depth); 7784993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes } 7794993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes 780734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes size_t current_stack_depth; 7812dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers std::vector<mirror::Object*> monitors; 782734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes std::vector<uint32_t> stack_depths; 7834993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes }; 7847a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers UniquePtr<Context> context(Context::Create()); 7857a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers OwnedMonitorVisitor visitor(thread, context.get()); 7864993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes visitor.WalkStack(); 7874993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes 7884993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes for (size_t i = 0; i < visitor.monitors.size(); ++i) { 7894993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes monitors.push_back(gRegistry->Add(visitor.monitors[i])); 790734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes stack_depths.push_back(visitor.stack_depths[i]); 7914993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes } 7924993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes 7934993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes return JDWP::ERR_NONE; 7944993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes} 7954993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes 79652d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien HertzJDWP::JdwpError Dbg::GetContendedMonitor(JDWP::ObjectId thread_id, 79752d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz JDWP::ObjectId& contended_monitor) { 798f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes ScopedObjectAccessUnchecked soa(Thread::Current()); 799f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 800f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes Thread* thread; 801f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); 802f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes if (error != JDWP::ERR_NONE) { 803f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes return error; 804f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes } 805f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes if (!IsSuspendedForDebugger(soa, thread)) { 806f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes return JDWP::ERR_THREAD_NOT_SUSPENDED; 807f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes } 808f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes 809f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes contended_monitor = gRegistry->Add(Monitor::GetContendedMonitor(thread)); 810f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes 811f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes return JDWP::ERR_NONE; 812f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes} 813f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes 814ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott HughesJDWP::JdwpError Dbg::GetInstanceCounts(const std::vector<JDWP::RefTypeId>& class_ids, 815ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes std::vector<uint64_t>& counts) 816ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 817412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier gc::Heap* heap = Runtime::Current()->GetHeap(); 818412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier heap->CollectGarbage(false); 8192dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers std::vector<mirror::Class*> classes; 820ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes counts.clear(); 821ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes for (size_t i = 0; i < class_ids.size(); ++i) { 822ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes JDWP::JdwpError status; 8232dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = DecodeClass(class_ids[i], status); 824ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes if (c == NULL) { 825ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes return status; 826ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes } 827ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes classes.push_back(c); 828ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes counts.push_back(0); 829ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes } 830412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier heap->CountInstances(classes, false, &counts[0]); 831ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes return JDWP::ERR_NONE; 832ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes} 833ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes 8343b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott HughesJDWP::JdwpError Dbg::GetInstances(JDWP::RefTypeId class_id, int32_t max_count, std::vector<JDWP::ObjectId>& instances) 8353b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 836412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier gc::Heap* heap = Runtime::Current()->GetHeap(); 837412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier // We only want reachable instances, so do a GC. 838412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier heap->CollectGarbage(false); 8393b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes JDWP::JdwpError status; 8402dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = DecodeClass(class_id, status); 841412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier if (c == nullptr) { 8423b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes return status; 8433b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes } 8442dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers std::vector<mirror::Object*> raw_instances; 8453b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes Runtime::Current()->GetHeap()->GetInstances(c, max_count, raw_instances); 8463b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes for (size_t i = 0; i < raw_instances.size(); ++i) { 8473b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes instances.push_back(gRegistry->Add(raw_instances[i])); 8483b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes } 8493b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes return JDWP::ERR_NONE; 8503b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes} 8513b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes 8520cbaff584244ee767027aff35cd3c625aaee2994Elliott HughesJDWP::JdwpError Dbg::GetReferringObjects(JDWP::ObjectId object_id, int32_t max_count, 8530cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes std::vector<JDWP::ObjectId>& referring_objects) 8540cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 855412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier gc::Heap* heap = Runtime::Current()->GetHeap(); 856412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier heap->CollectGarbage(false); 8572dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); 85864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (o == NULL || o == ObjectRegistry::kInvalidObject) { 8590cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 8600cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes } 8612dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers std::vector<mirror::Object*> raw_instances; 862412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier heap->GetReferringObjects(o, max_count, raw_instances); 8630cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes for (size_t i = 0; i < raw_instances.size(); ++i) { 8640cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes referring_objects.push_back(gRegistry->Add(raw_instances[i])); 8650cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes } 8660cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes return JDWP::ERR_NONE; 8670cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes} 8680cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes 86964f574f474aa77c72778640ab21f8cfa72546812Elliott HughesJDWP::JdwpError Dbg::DisableCollection(JDWP::ObjectId object_id) 87064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 871e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); 872e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz if (o == NULL || o == ObjectRegistry::kInvalidObject) { 873e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz return JDWP::ERR_INVALID_OBJECT; 874e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz } 87564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes gRegistry->DisableCollection(object_id); 87664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return JDWP::ERR_NONE; 87764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 87864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 87964f574f474aa77c72778640ab21f8cfa72546812Elliott HughesJDWP::JdwpError Dbg::EnableCollection(JDWP::ObjectId object_id) 88064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 881e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); 882e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz // Unlike DisableCollection, JDWP specs do not state an invalid object causes an error. The RI 883e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz // also ignores these cases and never return an error. However it's not obvious why this command 884e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz // should behave differently from DisableCollection and IsCollected commands. So let's be more 885e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz // strict and return an error if this happens. 886e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz if (o == NULL || o == ObjectRegistry::kInvalidObject) { 887e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz return JDWP::ERR_INVALID_OBJECT; 888e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz } 88964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes gRegistry->EnableCollection(object_id); 89064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return JDWP::ERR_NONE; 89164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 89264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 89364f574f474aa77c72778640ab21f8cfa72546812Elliott HughesJDWP::JdwpError Dbg::IsCollected(JDWP::ObjectId object_id, bool& is_collected) 89464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 89565637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz if (object_id == 0) { 89665637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz // Null object id is invalid. 89765637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz return JDWP::ERR_INVALID_OBJECT; 89865637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz } 899e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz // JDWP specs state an INVALID_OBJECT error is returned if the object ID is not valid. However 90065637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz // the RI seems to ignore this and assume object has been collected. 90165637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); 902e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz if (o == NULL || o == ObjectRegistry::kInvalidObject) { 90365637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz is_collected = true; 90465637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz } else { 90565637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz is_collected = gRegistry->IsCollected(object_id); 906e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz } 90764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return JDWP::ERR_NONE; 90864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 90964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 91064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid Dbg::DisposeObject(JDWP::ObjectId object_id, uint32_t reference_count) 91164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 91264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes gRegistry->DisposeObject(object_id, reference_count); 91364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 91464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 91588d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::GetReflectedType(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) { 916436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes JDWP::JdwpError status; 9172dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = DecodeClass(class_id, status); 918436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes if (c == NULL) { 919436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return status; 9207b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 921436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes 922436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes expandBufAdd1(pReply, c->IsInterface() ? JDWP::TT_INTERFACE : JDWP::TT_CLASS); 92388d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes expandBufAddRefTypeId(pReply, class_id); 924436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 925872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 926872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 9277b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughesvoid Dbg::GetClassList(std::vector<JDWP::RefTypeId>& classes) { 928a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // Get the complete list of reference classes (i.e. all classes except 929a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // the primitive types). 930a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // Returns a newly-allocated buffer full of RefTypeId values. 931a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes struct ClassListCreator { 932ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes explicit ClassListCreator(std::vector<JDWP::RefTypeId>& classes) : classes(classes) { 9337b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 9347b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes 9352dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers static bool Visit(mirror::Class* c, void* arg) { 936a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return reinterpret_cast<ClassListCreator*>(arg)->Visit(c); 937a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 938a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 93964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses 94064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes // annotalysis. 94164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes bool Visit(mirror::Class* c) NO_THREAD_SAFETY_ANALYSIS { 942a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes if (!c->IsPrimitive()) { 94364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes classes.push_back(gRegistry->AddRefType(c)); 944a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 945a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return true; 946a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 947a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 9487b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes std::vector<JDWP::RefTypeId>& classes; 949a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes }; 950a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 9517b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes ClassListCreator clc(classes); 952a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes Runtime::Current()->GetClassLinker()->VisitClasses(ClassListCreator::Visit, &clc); 953872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 954872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 95588d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* pTypeTag, uint32_t* pStatus, std::string* pDescriptor) { 956436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes JDWP::JdwpError status; 9572dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = DecodeClass(class_id, status); 958436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes if (c == NULL) { 959436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return status; 9607b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 9617b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes 962a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes if (c->IsArrayClass()) { 963a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes *pStatus = JDWP::CS_VERIFIED | JDWP::CS_PREPARED; 964a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes *pTypeTag = JDWP::TT_ARRAY; 965a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } else { 966a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes if (c->IsErroneous()) { 967a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes *pStatus = JDWP::CS_ERROR; 968a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } else { 969a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes *pStatus = JDWP::CS_VERIFIED | JDWP::CS_PREPARED | JDWP::CS_INITIALIZED; 970a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 971a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes *pTypeTag = c->IsInterface() ? JDWP::TT_INTERFACE : JDWP::TT_CLASS; 972a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 973a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 974a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes if (pDescriptor != NULL) { 975dfb325e0ddd746cd8f7c2e3723b3a573eb7cc111Ian Rogers *pDescriptor = ClassHelper(c).GetDescriptor(); 976a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 977436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 978872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 979872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 980c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughesvoid Dbg::FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>& ids) { 9812dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers std::vector<mirror::Class*> classes; 9826fa602d614d418f38afebb4d44f42e7dc0b4bd94Elliott Hughes Runtime::Current()->GetClassLinker()->LookupClasses(descriptor, classes); 9836fa602d614d418f38afebb4d44f42e7dc0b4bd94Elliott Hughes ids.clear(); 9846fa602d614d418f38afebb4d44f42e7dc0b4bd94Elliott Hughes for (size_t i = 0; i < classes.size(); ++i) { 9856fa602d614d418f38afebb4d44f42e7dc0b4bd94Elliott Hughes ids.push_back(gRegistry->Add(classes[i])); 9866fa602d614d418f38afebb4d44f42e7dc0b4bd94Elliott Hughes } 987872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 988872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 98964f574f474aa77c72778640ab21f8cfa72546812Elliott HughesJDWP::JdwpError Dbg::GetReferenceType(JDWP::ObjectId object_id, JDWP::ExpandBuf* pReply) 99064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 9912dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); 99264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (o == NULL || o == ObjectRegistry::kInvalidObject) { 9932435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 9942435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 9952435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 9962435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes JDWP::JdwpTypeTag type_tag; 997499c5133d361e7c659fc38e5ccfeb1280a7996f5Elliott Hughes if (o->GetClass()->IsArrayClass()) { 9982435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes type_tag = JDWP::TT_ARRAY; 999499c5133d361e7c659fc38e5ccfeb1280a7996f5Elliott Hughes } else if (o->GetClass()->IsInterface()) { 10002435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes type_tag = JDWP::TT_INTERFACE; 1001499c5133d361e7c659fc38e5ccfeb1280a7996f5Elliott Hughes } else { 10022435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes type_tag = JDWP::TT_CLASS; 1003499c5133d361e7c659fc38e5ccfeb1280a7996f5Elliott Hughes } 100464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes JDWP::RefTypeId type_id = gRegistry->AddRefType(o->GetClass()); 10052435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 10062435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes expandBufAdd1(pReply, type_tag); 10072435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes expandBufAddRefTypeId(pReply, type_id); 10082435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 10092435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes return JDWP::ERR_NONE; 1010872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1011872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1012fc0e94bed3f88ed7e50854fd8dfaf5dcb345250fIan RogersJDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId class_id, std::string* signature) { 10131fe7afb88498d48d1f808ee31e986324f2a1c842Elliott Hughes JDWP::JdwpError status; 10142dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = DecodeClass(class_id, status); 10151fe7afb88498d48d1f808ee31e986324f2a1c842Elliott Hughes if (c == NULL) { 10161fe7afb88498d48d1f808ee31e986324f2a1c842Elliott Hughes return status; 10177b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 1018dfb325e0ddd746cd8f7c2e3723b3a573eb7cc111Ian Rogers *signature = ClassHelper(c).GetDescriptor(); 10191fe7afb88498d48d1f808ee31e986324f2a1c842Elliott Hughes return JDWP::ERR_NONE; 1020872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1021872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 102288d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::GetSourceFile(JDWP::RefTypeId class_id, std::string& result) { 1023436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes JDWP::JdwpError status; 10242dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = DecodeClass(class_id, status); 1025436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes if (c == NULL) { 1026436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return status; 10277b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 1028b7054baf28d4d652fbd98a94b089344a31898d53Sebastien Hertz if (c->IsProxyClass()) { 1029b7054baf28d4d652fbd98a94b089344a31898d53Sebastien Hertz return JDWP::ERR_ABSENT_INFORMATION; 1030b7054baf28d4d652fbd98a94b089344a31898d53Sebastien Hertz } 1031436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes result = ClassHelper(c).GetSourceFile(); 1032436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 1033872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1034872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 103588d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::GetObjectTag(JDWP::ObjectId object_id, uint8_t& tag) { 10369837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 10372dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); 103864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (o == ObjectRegistry::kInvalidObject) { 1039546b986ecd09c2a498740bd8bf7127e612d94755Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 1040546b986ecd09c2a498740bd8bf7127e612d94755Elliott Hughes } 10419837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers tag = TagFromObject(soa, o); 1042546b986ecd09c2a498740bd8bf7127e612d94755Elliott Hughes return JDWP::ERR_NONE; 1043872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1044872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1045aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughessize_t Dbg::GetTagWidth(JDWP::JdwpTag tag) { 1046dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes switch (tag) { 1047dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_VOID: 1048dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes return 0; 1049dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_BYTE: 1050dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_BOOLEAN: 1051dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes return 1; 1052dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_CHAR: 1053dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_SHORT: 1054dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes return 2; 1055dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_FLOAT: 1056dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_INT: 1057dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes return 4; 1058dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_ARRAY: 1059dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_OBJECT: 1060dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_STRING: 1061dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_THREAD: 1062dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_THREAD_GROUP: 1063dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_CLASS_LOADER: 1064dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_CLASS_OBJECT: 1065dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes return sizeof(JDWP::ObjectId); 1066dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_DOUBLE: 1067dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_LONG: 1068dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes return 8; 1069dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes default: 10703d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes LOG(FATAL) << "Unknown tag " << tag; 1071dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes return -1; 1072dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes } 1073872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1074872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 107588d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::GetArrayLength(JDWP::ObjectId array_id, int& length) { 10763d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes JDWP::JdwpError status; 10772dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Array* a = DecodeArray(array_id, status); 10783d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes if (a == NULL) { 10793d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return status; 108024437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } 10813d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes length = a->GetLength(); 10823d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return JDWP::ERR_NONE; 1083872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1084872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 108588d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id, int offset, int count, JDWP::ExpandBuf* pReply) { 10863d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes JDWP::JdwpError status; 10872dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Array* a = DecodeArray(array_id, status); 10889837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers if (a == nullptr) { 10893d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return status; 10903d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes } 109124437995cdac88b42e42b16d9aa121e833330999Elliott Hughes 109224437995cdac88b42e42b16d9aa121e833330999Elliott Hughes if (offset < 0 || count < 0 || offset > a->GetLength() || a->GetLength() - offset < count) { 109324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count; 10943d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return JDWP::ERR_INVALID_LENGTH; 109524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } 10966d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers std::string descriptor(ClassHelper(a->GetClass()).GetDescriptor()); 109724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor.c_str() + 1); 109824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes 10993d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes expandBufAdd1(pReply, tag); 11003d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes expandBufAdd4BE(pReply, count); 11013d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes 110224437995cdac88b42e42b16d9aa121e833330999Elliott Hughes if (IsPrimitiveTag(tag)) { 110324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes size_t width = GetTagWidth(tag); 110424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes uint8_t* dst = expandBufAddSpace(pReply, count * width); 110524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes if (width == 8) { 1106ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const uint64_t* src8 = reinterpret_cast<uint64_t*>(a->GetRawData(sizeof(uint64_t), 0)); 110724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes for (int i = 0; i < count; ++i) JDWP::Write8BE(&dst, src8[offset + i]); 110824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } else if (width == 4) { 1109ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const uint32_t* src4 = reinterpret_cast<uint32_t*>(a->GetRawData(sizeof(uint32_t), 0)); 111024437995cdac88b42e42b16d9aa121e833330999Elliott Hughes for (int i = 0; i < count; ++i) JDWP::Write4BE(&dst, src4[offset + i]); 111124437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } else if (width == 2) { 1112ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const uint16_t* src2 = reinterpret_cast<uint16_t*>(a->GetRawData(sizeof(uint16_t), 0)); 111324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes for (int i = 0; i < count; ++i) JDWP::Write2BE(&dst, src2[offset + i]); 111424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } else { 1115ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const uint8_t* src = reinterpret_cast<uint8_t*>(a->GetRawData(sizeof(uint8_t), 0)); 111624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes memcpy(dst, &src[offset * width], count * width); 111724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } 111824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } else { 11199837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 11202dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::ObjectArray<mirror::Object>* oa = a->AsObjectArray<mirror::Object>(); 112124437995cdac88b42e42b16d9aa121e833330999Elliott Hughes for (int i = 0; i < count; ++i) { 11222dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* element = oa->Get(offset + i); 11239837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers JDWP::JdwpTag specific_tag = (element != nullptr) ? TagFromObject(soa, element) 11249837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers : tag; 112524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes expandBufAdd1(pReply, specific_tag); 112624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes expandBufAddObjectId(pReply, gRegistry->Add(element)); 112724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } 112824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } 112924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes 11303d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return JDWP::ERR_NONE; 1131872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1132872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1133ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogerstemplate <typename T> 1134ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersstatic void CopyArrayData(mirror::Array* a, JDWP::Request& src, int offset, int count) 1135ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers NO_THREAD_SAFETY_ANALYSIS { 1136ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers // TODO: fix when annotalysis correctly handles non-member functions. 11374b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes DCHECK(a->GetClass()->IsPrimitiveArray()); 11384b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes 1139ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers T* dst = reinterpret_cast<T*>(a->GetRawData(sizeof(T), offset)); 11404b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes for (int i = 0; i < count; ++i) { 11414b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes *dst++ = src.ReadValue(sizeof(T)); 11424b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes } 11434b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes} 11444b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes 114588d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::SetArrayElements(JDWP::ObjectId array_id, int offset, int count, 11464b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes JDWP::Request& request) 1147b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 11483d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes JDWP::JdwpError status; 11494b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes mirror::Array* dst = DecodeArray(array_id, status); 11504b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes if (dst == NULL) { 11513d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return status; 11523d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes } 1153f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes 11544b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes if (offset < 0 || count < 0 || offset > dst->GetLength() || dst->GetLength() - offset < count) { 1155f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count; 11563d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return JDWP::ERR_INVALID_LENGTH; 1157f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes } 1158fc0e94bed3f88ed7e50854fd8dfaf5dcb345250fIan Rogers const char* descriptor = ClassHelper(dst->GetClass()).GetDescriptor(); 1159fc0e94bed3f88ed7e50854fd8dfaf5dcb345250fIan Rogers JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor + 1); 1160f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes 1161f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes if (IsPrimitiveTag(tag)) { 1162f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes size_t width = GetTagWidth(tag); 1163f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes if (width == 8) { 11644b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes CopyArrayData<uint64_t>(dst, request, offset, count); 1165f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes } else if (width == 4) { 11664b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes CopyArrayData<uint32_t>(dst, request, offset, count); 1167f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes } else if (width == 2) { 11684b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes CopyArrayData<uint16_t>(dst, request, offset, count); 1169f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes } else { 11704b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes CopyArrayData<uint8_t>(dst, request, offset, count); 1171f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes } 1172f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes } else { 11734b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes mirror::ObjectArray<mirror::Object>* oa = dst->AsObjectArray<mirror::Object>(); 1174f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes for (int i = 0; i < count; ++i) { 11754b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes JDWP::ObjectId id = request.ReadObjectId(); 11762dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(id); 117764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (o == ObjectRegistry::kInvalidObject) { 1178436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 1179436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes } 1180d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz oa->Set<false>(offset + i, o); 1181f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes } 1182f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes } 1183f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes 11843d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return JDWP::ERR_NONE; 1185872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1186872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 11877b3cdfcca472b779cf8745fb8460935e56229f11Elliott HughesJDWP::ObjectId Dbg::CreateString(const std::string& str) { 11882dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers return gRegistry->Add(mirror::String::AllocFromModifiedUtf8(Thread::Current(), str.c_str())); 1189872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1190872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 119188d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::CreateObject(JDWP::RefTypeId class_id, JDWP::ObjectId& new_object) { 1192436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes JDWP::JdwpError status; 11932dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = DecodeClass(class_id, status); 1194436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes if (c == NULL) { 1195436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return status; 11967b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 119750b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers new_object = gRegistry->Add(c->AllocObject(Thread::Current())); 1198436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 1199872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1200872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1201bf13d36a25ec0a217fc4440c38b03d10f6c7f642Elliott Hughes/* 1202bf13d36a25ec0a217fc4440c38b03d10f6c7f642Elliott Hughes * Used by Eclipse's "Display" view to evaluate "new byte[5]" to get "(byte[]) [0, 0, 0, 0, 0]". 1203bf13d36a25ec0a217fc4440c38b03d10f6c7f642Elliott Hughes */ 120488d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::CreateArrayObject(JDWP::RefTypeId array_class_id, uint32_t length, 120500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JDWP::ObjectId& new_array) { 1206436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes JDWP::JdwpError status; 12072dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = DecodeClass(array_class_id, status); 1208436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes if (c == NULL) { 1209436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return status; 12107b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 12116fac447555dc94a935b78198479cce645c837b89Ian Rogers new_array = gRegistry->Add(mirror::Array::Alloc<true>(Thread::Current(), c, length, 12126fac447555dc94a935b78198479cce645c837b89Ian Rogers c->GetComponentSize(), 12136fac447555dc94a935b78198479cce645c837b89Ian Rogers Runtime::Current()->GetHeap()->GetCurrentAllocator())); 1214436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 1215872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1216872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 121788d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughesbool Dbg::MatchType(JDWP::RefTypeId instance_class_id, JDWP::RefTypeId class_id) { 1218436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes JDWP::JdwpError status; 12192dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c1 = DecodeClass(instance_class_id, status); 1220a656a0f6fbcf2ba3f15cae54a773b9c636dd32c1Elliott Hughes CHECK(c1 != NULL); 12212dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c2 = DecodeClass(class_id, status); 1222a656a0f6fbcf2ba3f15cae54a773b9c636dd32c1Elliott Hughes CHECK(c2 != NULL); 1223123756a041baf8421ed933312605daa5ef082f6fSebastien Hertz return c2->IsAssignableFrom(c1); 1224872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1225872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1226ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromstatic JDWP::FieldId ToFieldId(const mirror::ArtField* f) 1227b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 1228590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier CHECK(!kMovingFields); 122903181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes return static_cast<JDWP::FieldId>(reinterpret_cast<uintptr_t>(f)); 123003181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes} 123103181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 1232ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromstatic JDWP::MethodId ToMethodId(const mirror::ArtMethod* m) 1233b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 1234590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier CHECK(!kMovingMethods); 123503181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes return static_cast<JDWP::MethodId>(reinterpret_cast<uintptr_t>(m)); 123603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes} 123703181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 1238ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromstatic mirror::ArtField* FromFieldId(JDWP::FieldId fid) 1239b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 1240590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier CHECK(!kMovingFields); 1241ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom return reinterpret_cast<mirror::ArtField*>(static_cast<uintptr_t>(fid)); 1242aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes} 1243aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes 1244ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromstatic mirror::ArtMethod* FromMethodId(JDWP::MethodId mid) 1245b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 1246590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier CHECK(!kMovingMethods); 1247ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom return reinterpret_cast<mirror::ArtMethod*>(static_cast<uintptr_t>(mid)); 124803181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes} 124903181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 1250ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromstatic void SetLocation(JDWP::JdwpLocation& location, mirror::ArtMethod* m, uint32_t dex_pc) 1251b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 125291bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes if (m == NULL) { 125391bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes memset(&location, 0, sizeof(location)); 125491bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes } else { 12552dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = m->GetDeclaringClass(); 1256748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes location.type_tag = c->IsInterface() ? JDWP::TT_INTERFACE : JDWP::TT_CLASS; 1257cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz location.class_id = gRegistry->AddRefType(c); 1258748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes location.method_id = ToMethodId(m); 1259cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz location.dex_pc = (m->IsNative() || m->IsProxyMethod()) ? static_cast<uint64_t>(-1) : dex_pc; 126091bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes } 1261d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes} 1262d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 1263a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughesstd::string Dbg::GetMethodName(JDWP::MethodId method_id) 1264b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 1265ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* m = FromMethodId(method_id); 12666d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers return MethodHelper(m).GetName(); 1267872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1268872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1269a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughesstd::string Dbg::GetFieldName(JDWP::FieldId field_id) 1270a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 1271ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtField* f = FromFieldId(field_id); 1272a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes return FieldHelper(f).GetName(); 1273a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes} 1274a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes 1275a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes/* 1276a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes * Augment the access flags for synthetic methods and fields by setting 1277a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes * the (as described by the spec) "0xf0000000 bit". Also, strip out any 1278a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes * flags not specified by the Java programming language. 1279a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes */ 1280a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughesstatic uint32_t MangleAccessFlags(uint32_t accessFlags) { 1281a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes accessFlags &= kAccJavaFlagsMask; 1282a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes if ((accessFlags & kAccSynthetic) != 0) { 1283a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes accessFlags |= 0xf0000000; 1284a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes } 1285a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes return accessFlags; 1286872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1287872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1288dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes/* 1289b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao * Circularly shifts registers so that arguments come first. Debuggers 1290b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao * expect slots to begin with arguments, but dex code places them at 1291b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao * the end. 1292dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes */ 1293b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Haostatic uint16_t MangleSlot(uint16_t slot, mirror::ArtMethod* m) 1294b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 1295b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem(); 1296cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz if (code_item == nullptr) { 1297cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz // We should not get here for a method without code (native, proxy or abstract). Log it and 1298cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz // return the slot as is since all registers are arguments. 1299cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz LOG(WARNING) << "Trying to mangle slot for method without code " << PrettyMethod(m); 1300cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz return slot; 1301cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz } 1302b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao uint16_t ins_size = code_item->ins_size_; 1303b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao uint16_t locals_size = code_item->registers_size_ - ins_size; 1304b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao if (slot >= locals_size) { 1305b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao return slot - locals_size; 1306b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao } else { 1307b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao return slot + ins_size; 1308dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes } 1309dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes} 1310dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1311b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao/* 1312b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao * Circularly shifts registers so that arguments come last. Reverts 1313b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao * slots to dex style argument placement. 1314b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao */ 1315ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromstatic uint16_t DemangleSlot(uint16_t slot, mirror::ArtMethod* m) 1316b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 1317b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem(); 1318cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz if (code_item == nullptr) { 1319cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz // We should not get here for a method without code (native, proxy or abstract). Log it and 1320cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz // return the slot as is since all registers are arguments. 1321cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz LOG(WARNING) << "Trying to demangle slot for method without code " << PrettyMethod(m); 1322cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz return slot; 1323cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz } 1324b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao uint16_t ins_size = code_item->ins_size_; 1325b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao uint16_t locals_size = code_item->registers_size_ - ins_size; 1326b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao if (slot < ins_size) { 1327b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao return slot + locals_size; 1328b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao } else { 1329b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao return slot - ins_size; 1330dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes } 1331dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes} 1332dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 133388d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::OutputDeclaredFields(JDWP::RefTypeId class_id, bool with_generic, JDWP::ExpandBuf* pReply) { 1334436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes JDWP::JdwpError status; 13352dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = DecodeClass(class_id, status); 1336436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes if (c == NULL) { 1337436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return status; 13387b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 1339a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes 1340a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes size_t instance_field_count = c->NumInstanceFields(); 1341a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes size_t static_field_count = c->NumStaticFields(); 1342a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes 1343a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes expandBufAdd4BE(pReply, instance_field_count + static_field_count); 1344a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes 1345a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes for (size_t i = 0; i < instance_field_count + static_field_count; ++i) { 1346ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtField* f = (i < instance_field_count) ? c->GetInstanceField(i) : c->GetStaticField(i - instance_field_count); 13476d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers FieldHelper fh(f); 1348a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes expandBufAddFieldId(pReply, ToFieldId(f)); 13496d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers expandBufAddUtf8String(pReply, fh.GetName()); 13506d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers expandBufAddUtf8String(pReply, fh.GetTypeDescriptor()); 1351c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes if (with_generic) { 1352a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes static const char genericSignature[1] = ""; 1353a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes expandBufAddUtf8String(pReply, genericSignature); 1354a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes } 1355a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes expandBufAdd4BE(pReply, MangleAccessFlags(f->GetAccessFlags())); 1356a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes } 1357436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 1358a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes} 1359a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes 136088d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::OutputDeclaredMethods(JDWP::RefTypeId class_id, bool with_generic, 136100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JDWP::ExpandBuf* pReply) { 1362436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes JDWP::JdwpError status; 13632dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = DecodeClass(class_id, status); 1364436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes if (c == NULL) { 1365436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return status; 13667b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 1367a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes 1368a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes size_t direct_method_count = c->NumDirectMethods(); 1369a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes size_t virtual_method_count = c->NumVirtualMethods(); 1370a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes 1371a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes expandBufAdd4BE(pReply, direct_method_count + virtual_method_count); 1372a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes 1373a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes for (size_t i = 0; i < direct_method_count + virtual_method_count; ++i) { 1374ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* m = (i < direct_method_count) ? c->GetDirectMethod(i) : c->GetVirtualMethod(i - direct_method_count); 13756d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers MethodHelper mh(m); 1376a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes expandBufAddMethodId(pReply, ToMethodId(m)); 13776d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers expandBufAddUtf8String(pReply, mh.GetName()); 1378d91d6d6a80748f277fd938a412211e5af28913b1Ian Rogers expandBufAddUtf8String(pReply, mh.GetSignature().ToString()); 1379c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes if (with_generic) { 1380a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes static const char genericSignature[1] = ""; 1381a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes expandBufAddUtf8String(pReply, genericSignature); 1382a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes } 1383a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes expandBufAdd4BE(pReply, MangleAccessFlags(m->GetAccessFlags())); 1384a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes } 1385436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 1386a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes} 1387a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes 138888d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::OutputDeclaredInterfaces(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) { 1389436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes JDWP::JdwpError status; 13902dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = DecodeClass(class_id, status); 1391436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes if (c == NULL) { 1392436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return status; 13937b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 1394436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes 1395436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes ClassHelper kh(c); 1396d24e264ff85ad8c6f142ac6d33055fdc1881fa2fIan Rogers size_t interface_count = kh.NumDirectInterfaces(); 1397a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes expandBufAdd4BE(pReply, interface_count); 1398a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes for (size_t i = 0; i < interface_count; ++i) { 139964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes expandBufAddRefTypeId(pReply, gRegistry->AddRefType(kh.GetDirectInterface(i))); 1400a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes } 1401436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 1402872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1403872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 140488d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughesvoid Dbg::OutputLineTable(JDWP::RefTypeId, JDWP::MethodId method_id, JDWP::ExpandBuf* pReply) 1405b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 140603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes struct DebugCallbackContext { 140703181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes int numItems; 140803181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes JDWP::ExpandBuf* pReply; 140903181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 14102435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes static bool Callback(void* context, uint32_t address, uint32_t line_number) { 141103181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes DebugCallbackContext* pContext = reinterpret_cast<DebugCallbackContext*>(context); 141203181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes expandBufAdd8BE(pContext->pReply, address); 14132435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes expandBufAdd4BE(pContext->pReply, line_number); 141403181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes pContext->numItems++; 1415f2910eef247b45ce1d489e323b36b5de6b6157aaSebastien Hertz return false; 141603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes } 141703181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes }; 1418ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* m = FromMethodId(method_id); 14196d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers MethodHelper mh(m); 1420cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz const DexFile::CodeItem* code_item = mh.GetCodeItem(); 142103181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes uint64_t start, end; 1422cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz if (code_item == nullptr) { 1423cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz DCHECK(m->IsNative() || m->IsProxyMethod()); 142403181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes start = -1; 142503181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes end = -1; 142603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes } else { 142703181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes start = 0; 142814f0db92225d34622fa5cb1a6dc9287334aaf6c7jeffhao // Return the index of the last instruction 1429cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz end = code_item->insns_size_in_code_units_ - 1; 143003181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes } 143103181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 143203181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes expandBufAdd8BE(pReply, start); 143303181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes expandBufAdd8BE(pReply, end); 143403181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 143503181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes // Add numLines later 143603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes size_t numLinesOffset = expandBufGetLength(pReply); 143703181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes expandBufAdd4BE(pReply, 0); 143803181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 143903181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes DebugCallbackContext context; 144003181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes context.numItems = 0; 144103181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes context.pReply = pReply; 144203181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 1443cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz if (code_item != nullptr) { 1444cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz mh.GetDexFile().DecodeDebugInfo(code_item, m->IsStatic(), m->GetDexMethodIndex(), 1445cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz DebugCallbackContext::Callback, NULL, &context); 1446cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz } 144703181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 144803181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes JDWP::Set4BE(expandBufGetBuffer(pReply) + numLinesOffset, context.numItems); 1449872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1450872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 145188d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughesvoid Dbg::OutputVariableTable(JDWP::RefTypeId, JDWP::MethodId method_id, bool with_generic, JDWP::ExpandBuf* pReply) { 1452dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes struct DebugCallbackContext { 1453b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao mirror::ArtMethod* method; 1454dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes JDWP::ExpandBuf* pReply; 1455c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes size_t variable_count; 1456c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes bool with_generic; 1457dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1458b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao static void Callback(void* context, uint16_t slot, uint32_t startAddress, uint32_t endAddress, const char* name, const char* descriptor, const char* signature) 1459b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 1460dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes DebugCallbackContext* pContext = reinterpret_cast<DebugCallbackContext*>(context); 1461dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1462b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao VLOG(jdwp) << StringPrintf(" %2zd: %d(%d) '%s' '%s' '%s' actual slot=%d mangled slot=%d", pContext->variable_count, startAddress, endAddress - startAddress, name, descriptor, signature, slot, MangleSlot(slot, pContext->method)); 1463dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1464b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao slot = MangleSlot(slot, pContext->method); 146568fdbd07fc2b8856905e06f3cc945b046c3bfcd3Elliott Hughes 1466dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes expandBufAdd8BE(pContext->pReply, startAddress); 1467dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes expandBufAddUtf8String(pContext->pReply, name); 1468dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes expandBufAddUtf8String(pContext->pReply, descriptor); 1469c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes if (pContext->with_generic) { 1470dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes expandBufAddUtf8String(pContext->pReply, signature); 1471dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes } 1472dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes expandBufAdd4BE(pContext->pReply, endAddress - startAddress); 1473dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes expandBufAdd4BE(pContext->pReply, slot); 1474dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1475c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes ++pContext->variable_count; 1476dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes } 1477dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes }; 1478ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* m = FromMethodId(method_id); 14796d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers MethodHelper mh(m); 1480dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1481c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes // arg_count considers doubles and longs to take 2 units. 1482c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes // variable_count considers everything to take 1 unit. 14836d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers std::string shorty(mh.GetShorty()); 1484ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom expandBufAdd4BE(pReply, mirror::ArtMethod::NumArgRegisters(shorty)); 1485dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1486c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes // We don't know the total number of variables yet, so leave a blank and update it later. 1487c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes size_t variable_count_offset = expandBufGetLength(pReply); 1488dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes expandBufAdd4BE(pReply, 0); 1489dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1490dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes DebugCallbackContext context; 1491b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao context.method = m; 1492dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes context.pReply = pReply; 1493c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes context.variable_count = 0; 1494c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes context.with_generic = with_generic; 1495dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1496cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz const DexFile::CodeItem* code_item = mh.GetCodeItem(); 1497cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz if (code_item != nullptr) { 1498cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz mh.GetDexFile().DecodeDebugInfo(code_item, m->IsStatic(), m->GetDexMethodIndex(), NULL, 1499cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz DebugCallbackContext::Callback, &context); 1500cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz } 1501dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1502c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes JDWP::Set4BE(expandBufGetBuffer(pReply) + variable_count_offset, context.variable_count); 1503872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1504872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1505579b02416e05e32e535126e1ed61613a2cdb030eJeff Haovoid Dbg::OutputMethodReturnValue(JDWP::MethodId method_id, const JValue* return_value, 1506579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao JDWP::ExpandBuf* pReply) { 1507579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao mirror::ArtMethod* m = FromMethodId(method_id); 1508579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao JDWP::JdwpTag tag = BasicTagFromDescriptor(MethodHelper(m).GetShorty()); 1509579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao OutputJValue(tag, return_value, pReply); 1510579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao} 1511579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao 15129777ba230c83a0edcbda2cf7b208339e77bf171bElliott HughesJDWP::JdwpError Dbg::GetBytecodes(JDWP::RefTypeId, JDWP::MethodId method_id, 15139777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes std::vector<uint8_t>& bytecodes) 15149777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 1515ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* m = FromMethodId(method_id); 15169777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes if (m == NULL) { 15179777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes return JDWP::ERR_INVALID_METHODID; 15189777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes } 15199777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes MethodHelper mh(m); 15209777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes const DexFile::CodeItem* code_item = mh.GetCodeItem(); 15219777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes size_t byte_count = code_item->insns_size_in_code_units_ * 2; 15229777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes const uint8_t* begin = reinterpret_cast<const uint8_t*>(code_item->insns_); 15239777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes const uint8_t* end = begin + byte_count; 15249777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes for (const uint8_t* p = begin; p != end; ++p) { 15259777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes bytecodes.push_back(*p); 15269777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes } 15279777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes return JDWP::ERR_NONE; 15289777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes} 15299777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes 153088d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpTag Dbg::GetFieldBasicTag(JDWP::FieldId field_id) { 153188d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes return BasicTagFromDescriptor(FieldHelper(FromFieldId(field_id)).GetTypeDescriptor()); 1532872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1533872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 153488d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpTag Dbg::GetStaticFieldBasicTag(JDWP::FieldId field_id) { 153588d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes return BasicTagFromDescriptor(FieldHelper(FromFieldId(field_id)).GetTypeDescriptor()); 1536872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1537872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 153888d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughesstatic JDWP::JdwpError GetFieldValueImpl(JDWP::RefTypeId ref_type_id, JDWP::ObjectId object_id, 153988d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes JDWP::FieldId field_id, JDWP::ExpandBuf* pReply, 154000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool is_static) 1541b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 15420cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes JDWP::JdwpError status; 15432dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = DecodeClass(ref_type_id, status); 154488d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes if (ref_type_id != 0 && c == NULL) { 15450cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes return status; 15460cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes } 15470cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes 15482dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); 154964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if ((!is_static && o == NULL) || o == ObjectRegistry::kInvalidObject) { 15503f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 15513f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes } 1552ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtField* f = FromFieldId(field_id); 15530cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes 15542dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* receiver_class = c; 15550cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes if (receiver_class == NULL && o != NULL) { 15560cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes receiver_class = o->GetClass(); 15570cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes } 15580cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes // TODO: should we give up now if receiver_class is NULL? 15590cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes if (receiver_class != NULL && !f->GetDeclaringClass()->IsAssignableFrom(receiver_class)) { 15600cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes LOG(INFO) << "ERR_INVALID_FIELDID: " << PrettyField(f) << " " << PrettyClass(receiver_class); 15613f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes return JDWP::ERR_INVALID_FIELDID; 15623f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes } 1563aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes 15640cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes // The RI only enforces the static/non-static mismatch in one direction. 15650cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes // TODO: should we change the tests and check both? 15660cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes if (is_static) { 15670cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes if (!f->IsStatic()) { 15680cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes return JDWP::ERR_INVALID_FIELDID; 15690cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes } 15700cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes } else { 15710cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes if (f->IsStatic()) { 15720cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes LOG(WARNING) << "Ignoring non-NULL receiver for ObjectReference.SetValues on static field " << PrettyField(f); 15730cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes } 15740cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes } 15750dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao if (f->IsStatic()) { 15760dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao o = f->GetDeclaringClass(); 15770dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao } 15780cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes 15796d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers JDWP::JdwpTag tag = BasicTagFromDescriptor(FieldHelper(f).GetTypeDescriptor()); 1580579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao JValue field_value; 1581579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao if (tag == JDWP::JT_VOID) { 1582579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao LOG(FATAL) << "Unknown tag: " << tag; 1583579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao } else if (!IsPrimitiveTag(tag)) { 1584579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao field_value.SetL(f->GetObject(o)); 1585579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao } else if (tag == JDWP::JT_DOUBLE || tag == JDWP::JT_LONG) { 1586579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao field_value.SetJ(f->Get64(o)); 1587aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes } else { 1588579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao field_value.SetI(f->Get32(o)); 1589aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes } 1590579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao Dbg::OutputJValue(tag, &field_value, pReply); 1591579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao 15923f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes return JDWP::ERR_NONE; 1593872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1594872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 159588d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::GetFieldValue(JDWP::ObjectId object_id, JDWP::FieldId field_id, 159600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JDWP::ExpandBuf* pReply) { 159788d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes return GetFieldValueImpl(0, object_id, field_id, pReply, false); 15983f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes} 15993f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes 160088d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::GetStaticFieldValue(JDWP::RefTypeId ref_type_id, JDWP::FieldId field_id, JDWP::ExpandBuf* pReply) { 160188d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes return GetFieldValueImpl(ref_type_id, 0, field_id, pReply, true); 16023f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes} 16033f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes 160488d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughesstatic JDWP::JdwpError SetFieldValueImpl(JDWP::ObjectId object_id, JDWP::FieldId field_id, 160500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers uint64_t value, int width, bool is_static) 1606b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 16072dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); 160864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if ((!is_static && o == NULL) || o == ObjectRegistry::kInvalidObject) { 16093f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 16103f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes } 1611ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtField* f = FromFieldId(field_id); 16120cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes 16130cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes // The RI only enforces the static/non-static mismatch in one direction. 16140cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes // TODO: should we change the tests and check both? 16150cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes if (is_static) { 16160cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes if (!f->IsStatic()) { 16170cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes return JDWP::ERR_INVALID_FIELDID; 16180cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes } 16190cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes } else { 16200cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes if (f->IsStatic()) { 16210cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes LOG(WARNING) << "Ignoring non-NULL receiver for ObjectReference.SetValues on static field " << PrettyField(f); 16220cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes } 16233f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes } 16240dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao if (f->IsStatic()) { 16250dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao o = f->GetDeclaringClass(); 16260dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao } 1627aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes 16286d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers JDWP::JdwpTag tag = BasicTagFromDescriptor(FieldHelper(f).GetTypeDescriptor()); 1629aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes 1630aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes if (IsPrimitiveTag(tag)) { 1631aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes if (tag == JDWP::JT_DOUBLE || tag == JDWP::JT_LONG) { 16321bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes CHECK_EQ(width, 8); 1633d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // Debugging can't use transactional mode (runtime only). 1634d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz f->Set64<false>(o, value); 1635aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes } else { 16361bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes CHECK_LE(width, 4); 1637d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // Debugging can't use transactional mode (runtime only). 1638d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz f->Set32<false>(o, value); 1639aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes } 1640aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes } else { 16412dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* v = gRegistry->Get<mirror::Object*>(value); 164264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (v == ObjectRegistry::kInvalidObject) { 16433d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return JDWP::ERR_INVALID_OBJECT; 16443d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes } 16453f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes if (v != NULL) { 16462dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* field_type = FieldHelper(f).GetType(); 16473f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes if (!field_type->IsAssignableFrom(v->GetClass())) { 16483f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 16493f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes } 16503f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes } 1651d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // Debugging can't use transactional mode (runtime only). 1652d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz f->SetObject<false>(o, v); 1653aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes } 16543d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes 16553d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return JDWP::ERR_NONE; 1656872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1657872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 165888d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::SetFieldValue(JDWP::ObjectId object_id, JDWP::FieldId field_id, uint64_t value, 165900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers int width) { 166088d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes return SetFieldValueImpl(object_id, field_id, value, width, false); 1661872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1662872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 166388d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::SetStaticFieldValue(JDWP::FieldId field_id, uint64_t value, int width) { 166488d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes return SetFieldValueImpl(0, field_id, value, width, true); 1665872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1666872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 166788d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughesstd::string Dbg::StringToUtf8(JDWP::ObjectId string_id) { 16682dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::String* s = gRegistry->Get<mirror::String*>(string_id); 166968fdbd07fc2b8856905e06f3cc945b046c3bfcd3Elliott Hughes return s->ToModifiedUtf8(); 1670872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1671872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1672579b02416e05e32e535126e1ed61613a2cdb030eJeff Haovoid Dbg::OutputJValue(JDWP::JdwpTag tag, const JValue* return_value, JDWP::ExpandBuf* pReply) { 1673579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao if (IsPrimitiveTag(tag)) { 1674579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao expandBufAdd1(pReply, tag); 1675579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao if (tag == JDWP::JT_BOOLEAN || tag == JDWP::JT_BYTE) { 1676579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao expandBufAdd1(pReply, return_value->GetI()); 1677579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao } else if (tag == JDWP::JT_CHAR || tag == JDWP::JT_SHORT) { 1678579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao expandBufAdd2BE(pReply, return_value->GetI()); 1679579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao } else if (tag == JDWP::JT_FLOAT || tag == JDWP::JT_INT) { 1680579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao expandBufAdd4BE(pReply, return_value->GetI()); 1681579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao } else if (tag == JDWP::JT_DOUBLE || tag == JDWP::JT_LONG) { 1682579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao expandBufAdd8BE(pReply, return_value->GetJ()); 1683579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao } else { 1684579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao CHECK_EQ(tag, JDWP::JT_VOID); 1685579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao } 1686579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao } else { 16879837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 1688579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao mirror::Object* value = return_value->GetL(); 16899837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers expandBufAdd1(pReply, TagFromObject(soa, value)); 1690579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao expandBufAddObjectId(pReply, gRegistry->Add(value)); 1691579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao } 1692579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao} 1693579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao 1694221229cb523f849f165fdafbf9785010963715daElliott HughesJDWP::JdwpError Dbg::GetThreadName(JDWP::ObjectId thread_id, std::string& name) { 1695a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao ScopedObjectAccessUnchecked soa(Thread::Current()); 1696a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 1697221229cb523f849f165fdafbf9785010963715daElliott Hughes Thread* thread; 1698221229cb523f849f165fdafbf9785010963715daElliott Hughes JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); 1699221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error != JDWP::ERR_NONE && error != JDWP::ERR_THREAD_NOT_ALIVE) { 1700221229cb523f849f165fdafbf9785010963715daElliott Hughes return error; 1701a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes } 1702221229cb523f849f165fdafbf9785010963715daElliott Hughes 1703221229cb523f849f165fdafbf9785010963715daElliott Hughes // We still need to report the zombie threads' names, so we can't just call Thread::GetThreadName. 17042dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* thread_object = gRegistry->Get<mirror::Object*>(thread_id); 1705ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtField* java_lang_Thread_name_field = 17062dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers soa.DecodeField(WellKnownClasses::java_lang_Thread_name); 17072dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::String* s = 17082dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers reinterpret_cast<mirror::String*>(java_lang_Thread_name_field->GetObject(thread_object)); 1709221229cb523f849f165fdafbf9785010963715daElliott Hughes if (s != NULL) { 1710221229cb523f849f165fdafbf9785010963715daElliott Hughes name = s->ToModifiedUtf8(); 1711221229cb523f849f165fdafbf9785010963715daElliott Hughes } 1712221229cb523f849f165fdafbf9785010963715daElliott Hughes return JDWP::ERR_NONE; 1713872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1714872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1715221229cb523f849f165fdafbf9785010963715daElliott HughesJDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply) { 171600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 17172dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* thread_object = gRegistry->Get<mirror::Object*>(thread_id); 171864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (thread_object == ObjectRegistry::kInvalidObject) { 17192435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 17202435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 17219837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers const char* old_cause = soa.Self()->StartAssertNoThreadSuspension("Debugger: GetThreadGroup"); 17222435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // Okay, so it's an object, but is it actually a thread? 172350b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 1724221229cb523f849f165fdafbf9785010963715daElliott Hughes Thread* thread; 1725221229cb523f849f165fdafbf9785010963715daElliott Hughes JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); 1726221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error == JDWP::ERR_THREAD_NOT_ALIVE) { 1727221229cb523f849f165fdafbf9785010963715daElliott Hughes // Zombie threads are in the null group. 1728221229cb523f849f165fdafbf9785010963715daElliott Hughes expandBufAddObjectId(pReply, JDWP::ObjectId(0)); 172952d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz error = JDWP::ERR_NONE; 173052d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz } else if (error == JDWP::ERR_NONE) { 173152d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz mirror::Class* c = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread); 173252d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz CHECK(c != nullptr); 173352d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz mirror::ArtField* f = c->FindInstanceField("group", "Ljava/lang/ThreadGroup;"); 173452d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz CHECK(f != NULL); 173552d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz mirror::Object* group = f->GetObject(thread_object); 173652d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz CHECK(group != NULL); 173752d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz JDWP::ObjectId thread_group_id = gRegistry->Add(group); 173852d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz expandBufAddObjectId(pReply, thread_group_id); 17392435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 17409837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers soa.Self()->EndAssertNoThreadSuspension(old_cause); 174152d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz return error; 1742872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1743872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 174488d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughesstd::string Dbg::GetThreadGroupName(JDWP::ObjectId thread_group_id) { 174500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 17462dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id); 17479837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers CHECK(thread_group != nullptr); 17489837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers const char* old_cause = soa.Self()->StartAssertNoThreadSuspension("Debugger: GetThreadGroupName"); 17499837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers mirror::Class* c = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ThreadGroup); 17509837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers CHECK(c != nullptr); 1751ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtField* f = c->FindInstanceField("name", "Ljava/lang/String;"); 1752499c5133d361e7c659fc38e5ccfeb1280a7996f5Elliott Hughes CHECK(f != NULL); 17532dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::String* s = reinterpret_cast<mirror::String*>(f->GetObject(thread_group)); 17549837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers soa.Self()->EndAssertNoThreadSuspension(old_cause); 1755499c5133d361e7c659fc38e5ccfeb1280a7996f5Elliott Hughes return s->ToModifiedUtf8(); 1756872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1757872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 175888d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::ObjectId Dbg::GetThreadGroupParent(JDWP::ObjectId thread_group_id) { 17599837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 17602dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id); 17619837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers CHECK(thread_group != nullptr); 17629837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers const char* old_cause = soa.Self()->StartAssertNoThreadSuspension("Debugger: GetThreadGroupParent"); 17639837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers mirror::Class* c = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ThreadGroup); 17649837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers CHECK(c != nullptr); 1765ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtField* f = c->FindInstanceField("parent", "Ljava/lang/ThreadGroup;"); 17664e235316b4ada4d865c544d9b4ba397139333fa6Elliott Hughes CHECK(f != NULL); 17672dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* parent = f->GetObject(thread_group); 17689837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers soa.Self()->EndAssertNoThreadSuspension(old_cause); 17694e235316b4ada4d865c544d9b4ba397139333fa6Elliott Hughes return gRegistry->Add(parent); 1770872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1771872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1772872d4ec7225444d9400d30f9027247deb91012fdElliott HughesJDWP::ObjectId Dbg::GetSystemThreadGroupId() { 177300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 1774ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup); 17752dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* group = f->GetObject(f->GetDeclaringClass()); 1776365c10235438607541fa2259a5fec48061b90bd8Ian Rogers return gRegistry->Add(group); 1777872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1778872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1779872d4ec7225444d9400d30f9027247deb91012fdElliott HughesJDWP::ObjectId Dbg::GetMainThreadGroupId() { 178000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 1781ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_mainThreadGroup); 17822dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* group = f->GetObject(f->GetDeclaringClass()); 1783365c10235438607541fa2259a5fec48061b90bd8Ian Rogers return gRegistry->Add(group); 1784872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1785872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1786920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff HaoJDWP::JdwpThreadStatus Dbg::ToJdwpThreadStatus(ThreadState state) { 1787920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao switch (state) { 1788920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kBlocked: 1789920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao return JDWP::TS_MONITOR; 1790920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kNative: 1791920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kRunnable: 1792920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kSuspended: 1793920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao return JDWP::TS_RUNNING; 1794920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kSleeping: 1795920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao return JDWP::TS_SLEEPING; 1796920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kStarting: 1797920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kTerminated: 1798920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao return JDWP::TS_ZOMBIE; 1799920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kTimedWaiting: 1800920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingForDebuggerSend: 1801920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingForDebuggerSuspension: 1802920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingForDebuggerToAttach: 1803138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz case kWaitingForDeoptimization: 1804920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingForGcToComplete: 1805920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingForCheckPointsToRun: 1806920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingForJniOnLoad: 1807920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingForSignalCatcherOutput: 1808920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingInMainDebuggerLoop: 1809920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingInMainSignalCatcherLoop: 1810920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingPerformingGc: 1811920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaiting: 1812920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao return JDWP::TS_WAIT; 1813920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao // Don't add a 'default' here so the compiler can spot incompatible enum changes. 1814920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao } 1815920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao LOG(FATAL) << "Unknown thread state: " << state; 1816920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao return JDWP::TS_ZOMBIE; 1817920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao} 1818920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao 181952d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien HertzJDWP::JdwpError Dbg::GetThreadStatus(JDWP::ObjectId thread_id, JDWP::JdwpThreadStatus* pThreadStatus, 182052d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz JDWP::JdwpSuspendStatus* pSuspendStatus) { 182100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 1822499c5133d361e7c659fc38e5ccfeb1280a7996f5Elliott Hughes 18239e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes *pSuspendStatus = JDWP::SUSPEND_STATUS_NOT_SUSPENDED; 18249e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes 182550b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 1826221229cb523f849f165fdafbf9785010963715daElliott Hughes Thread* thread; 1827221229cb523f849f165fdafbf9785010963715daElliott Hughes JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); 1828221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error != JDWP::ERR_NONE) { 1829221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error == JDWP::ERR_THREAD_NOT_ALIVE) { 1830221229cb523f849f165fdafbf9785010963715daElliott Hughes *pThreadStatus = JDWP::TS_ZOMBIE; 1831221229cb523f849f165fdafbf9785010963715daElliott Hughes return JDWP::ERR_NONE; 1832221229cb523f849f165fdafbf9785010963715daElliott Hughes } 1833221229cb523f849f165fdafbf9785010963715daElliott Hughes return error; 1834499c5133d361e7c659fc38e5ccfeb1280a7996f5Elliott Hughes } 1835499c5133d361e7c659fc38e5ccfeb1280a7996f5Elliott Hughes 18369e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes if (IsSuspendedForDebugger(soa, thread)) { 18379e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes *pSuspendStatus = JDWP::SUSPEND_STATUS_SUSPENDED; 18389e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes } 183900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 1840920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao *pThreadStatus = ToJdwpThreadStatus(thread->GetState()); 1841221229cb523f849f165fdafbf9785010963715daElliott Hughes return JDWP::ERR_NONE; 1842872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1843872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1844221229cb523f849f165fdafbf9785010963715daElliott HughesJDWP::JdwpError Dbg::GetThreadDebugSuspendCount(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply) { 184500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 184650b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 1847221229cb523f849f165fdafbf9785010963715daElliott Hughes Thread* thread; 1848221229cb523f849f165fdafbf9785010963715daElliott Hughes JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); 1849221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error != JDWP::ERR_NONE) { 1850221229cb523f849f165fdafbf9785010963715daElliott Hughes return error; 18512435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 185250b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_); 185300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers expandBufAdd4BE(pReply, thread->GetDebugSuspendCount()); 18542435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes return JDWP::ERR_NONE; 1855872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1856872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1857f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott HughesJDWP::JdwpError Dbg::Interrupt(JDWP::ObjectId thread_id) { 1858f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes ScopedObjectAccess soa(Thread::Current()); 1859f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 1860f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes Thread* thread; 1861f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); 1862f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes if (error != JDWP::ERR_NONE) { 1863f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes return error; 1864f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes } 1865f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes thread->Interrupt(); 1866f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes return JDWP::ERR_NONE; 1867f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes} 1868f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes 1869caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughesvoid Dbg::GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>& thread_ids) { 1870365c10235438607541fa2259a5fec48061b90bd8Ian Rogers class ThreadListVisitor { 1871365c10235438607541fa2259a5fec48061b90bd8Ian Rogers public: 18722dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers ThreadListVisitor(const ScopedObjectAccessUnchecked& soa, mirror::Object* desired_thread_group, 187300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers std::vector<JDWP::ObjectId>& thread_ids) 1874b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 18750dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao : soa_(soa), desired_thread_group_(desired_thread_group), thread_ids_(thread_ids) {} 1876365c10235438607541fa2259a5fec48061b90bd8Ian Rogers 1877a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes static void Visit(Thread* t, void* arg) { 1878a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes reinterpret_cast<ThreadListVisitor*>(arg)->Visit(t); 1879a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 1880a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 188100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses 188200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // annotalysis. 188300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void Visit(Thread* t) NO_THREAD_SAFETY_ANALYSIS { 1884a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes if (t == Dbg::GetDebugThread()) { 1885a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // Skip the JDWP thread. Some debuggers get bent out of shape when they can't suspend and 1886a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // query all threads, so it's easier if we just don't tell them about this thread. 1887a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return; 1888a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 18892dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* peer = t->GetPeer(); 18900dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao if (IsInDesiredThreadGroup(peer)) { 1891120f1c74a9768e958377b6c97897511b27ae58c8Ian Rogers thread_ids_.push_back(gRegistry->Add(peer)); 1892a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 1893a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 1894a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 1895365c10235438607541fa2259a5fec48061b90bd8Ian Rogers private: 18962dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers bool IsInDesiredThreadGroup(mirror::Object* peer) 18970dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 18980dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao // peer might be NULL if the thread is still starting up. 18990dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao if (peer == NULL) { 19000dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao // We can't tell the debugger about this thread yet. 19010dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao // TODO: if we identified threads to the debugger by their Thread* 19022dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers // rather than their peer's mirror::Object*, we could fix this. 19030dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao // Doing so might help us report ZOMBIE threads too. 19040dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao return false; 19050dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao } 1906c1e0490a2a0293fdfc5f654482339ccc71d9952bjeffhao // Do we want threads from all thread groups? 1907c1e0490a2a0293fdfc5f654482339ccc71d9952bjeffhao if (desired_thread_group_ == NULL) { 1908c1e0490a2a0293fdfc5f654482339ccc71d9952bjeffhao return true; 1909c1e0490a2a0293fdfc5f654482339ccc71d9952bjeffhao } 19102dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* group = soa_.DecodeField(WellKnownClasses::java_lang_Thread_group)->GetObject(peer); 19110dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao return (group == desired_thread_group_); 19120dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao } 19130dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao 1914dbe6f4613ae0161b169f4fca8a616b0b393370abMathieu Chartier const ScopedObjectAccessUnchecked& soa_; 19152dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* const desired_thread_group_; 1916caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughes std::vector<JDWP::ObjectId>& thread_ids_; 1917a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes }; 1918a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 191900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 19202dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id); 192100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ThreadListVisitor tlv(soa, thread_group, thread_ids); 192250b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 1923f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes Runtime::Current()->GetThreadList()->ForEach(ThreadListVisitor::Visit, &tlv); 1924a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes} 1925a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 1926caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughesvoid Dbg::GetChildThreadGroups(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>& child_thread_group_ids) { 192700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 19282dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id); 1929caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughes 1930caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughes // Get the ArrayList<ThreadGroup> "groups" out of this thread group... 1931ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtField* groups_field = thread_group->GetClass()->FindInstanceField("groups", "Ljava/util/List;"); 19322dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* groups_array_list = groups_field->GetObject(thread_group); 1933872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1934caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughes // Get the array and size out of the ArrayList<ThreadGroup>... 1935ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtField* array_field = groups_array_list->GetClass()->FindInstanceField("array", "[Ljava/lang/Object;"); 1936ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtField* size_field = groups_array_list->GetClass()->FindInstanceField("size", "I"); 19372dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::ObjectArray<mirror::Object>* groups_array = 19382dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers array_field->GetObject(groups_array_list)->AsObjectArray<mirror::Object>(); 1939caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughes const int32_t size = size_field->GetInt(groups_array_list); 1940caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughes 1941caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughes // Copy the first 'size' elements out of the array into the result. 1942caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughes for (int32_t i = 0; i < size; ++i) { 1943caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughes child_thread_group_ids.push_back(gRegistry->Add(groups_array->Get(i))); 1944caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughes } 1945872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1946872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 194700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic int GetStackDepth(Thread* thread) 1948b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 19490399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers struct CountStackDepthVisitor : public StackVisitor { 195093ba893c20532990a430741e0a97212900094e8cBrian Carlstrom explicit CountStackDepthVisitor(Thread* thread) 19517a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers : StackVisitor(thread, NULL), depth(0) {} 19520399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers 195364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses 195464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes // annotalysis. 195564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { 19560399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers if (!GetMethod()->IsRuntimeMethod()) { 1957f8a2df7bbf1021058bc13d1f806a7fec3c89ee62Elliott Hughes ++depth; 1958f8a2df7bbf1021058bc13d1f806a7fec3c89ee62Elliott Hughes } 1959530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return true; 1960a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes } 1961a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes size_t depth; 1962a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes }; 196308fc03ae5dded4adc9b45b7014a4b9dfedbe95a6Elliott Hughes 19647a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers CountStackDepthVisitor visitor(thread); 19650399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers visitor.WalkStack(); 1966a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes return visitor.depth; 1967872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1968872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1969221229cb523f849f165fdafbf9785010963715daElliott HughesJDWP::JdwpError Dbg::GetThreadFrameCount(JDWP::ObjectId thread_id, size_t& result) { 197000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 1971a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 1972221229cb523f849f165fdafbf9785010963715daElliott Hughes Thread* thread; 1973221229cb523f849f165fdafbf9785010963715daElliott Hughes JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); 1974221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error != JDWP::ERR_NONE) { 1975221229cb523f849f165fdafbf9785010963715daElliott Hughes return error; 1976221229cb523f849f165fdafbf9785010963715daElliott Hughes } 1977f15f4a0136a7b797117355768851bc421b3afc93Elliott Hughes if (!IsSuspendedForDebugger(soa, thread)) { 1978f15f4a0136a7b797117355768851bc421b3afc93Elliott Hughes return JDWP::ERR_THREAD_NOT_SUSPENDED; 1979f15f4a0136a7b797117355768851bc421b3afc93Elliott Hughes } 1980221229cb523f849f165fdafbf9785010963715daElliott Hughes result = GetStackDepth(thread); 1981221229cb523f849f165fdafbf9785010963715daElliott Hughes return JDWP::ERR_NONE; 19828696433d1b3d8ba15288483b777edd888de69135Elliott Hughes} 19838696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 1984306057fd278d75bf3794bd5243a3b6652c487d18Ian RogersJDWP::JdwpError Dbg::GetThreadFrames(JDWP::ObjectId thread_id, size_t start_frame, 1985306057fd278d75bf3794bd5243a3b6652c487d18Ian Rogers size_t frame_count, JDWP::ExpandBuf* buf) { 19866e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes class GetFrameVisitor : public StackVisitor { 19876e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes public: 19887a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers GetFrameVisitor(Thread* thread, size_t start_frame, size_t frame_count, JDWP::ExpandBuf* buf) 1989b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 19907a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers : StackVisitor(thread, NULL), depth_(0), 19916e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes start_frame_(start_frame), frame_count_(frame_count), buf_(buf) { 19926e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes expandBufAdd4BE(buf_, frame_count_); 199303181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes } 19940399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers 199500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses 199600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // annotalysis. 199700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers virtual bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { 19980399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers if (GetMethod()->IsRuntimeMethod()) { 19997934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom return true; // The debugger can't do anything useful with a frame that has no Method*. 200003181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes } 20016e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes if (depth_ >= start_frame_ + frame_count_) { 2002530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return false; 200303181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes } 20046e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes if (depth_ >= start_frame_) { 20056e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes JDWP::FrameId frame_id(GetFrameId()); 20066e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes JDWP::JdwpLocation location; 20076e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes SetLocation(location, GetMethod(), GetDexPc()); 2008ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers VLOG(jdwp) << StringPrintf(" Frame %3zd: id=%3" PRIu64 " ", depth_, frame_id) << location; 20096e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes expandBufAdd8BE(buf_, frame_id); 20106e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes expandBufAddLocation(buf_, location); 20116e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes } 20126e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes ++depth_; 2013530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return true; 201403181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes } 20156e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes 20166e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes private: 20176e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes size_t depth_; 20186e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes const size_t start_frame_; 20196e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes const size_t frame_count_; 20206e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes JDWP::ExpandBuf* buf_; 202103181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes }; 202200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 202300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 2024a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 2025221229cb523f849f165fdafbf9785010963715daElliott Hughes Thread* thread; 2026221229cb523f849f165fdafbf9785010963715daElliott Hughes JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); 2027221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error != JDWP::ERR_NONE) { 2028221229cb523f849f165fdafbf9785010963715daElliott Hughes return error; 2029221229cb523f849f165fdafbf9785010963715daElliott Hughes } 2030f15f4a0136a7b797117355768851bc421b3afc93Elliott Hughes if (!IsSuspendedForDebugger(soa, thread)) { 2031f15f4a0136a7b797117355768851bc421b3afc93Elliott Hughes return JDWP::ERR_THREAD_NOT_SUSPENDED; 2032f15f4a0136a7b797117355768851bc421b3afc93Elliott Hughes } 20337a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers GetFrameVisitor visitor(thread, start_frame, frame_count, buf); 20340399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers visitor.WalkStack(); 20356e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes return JDWP::ERR_NONE; 2036872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2037872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2038872d4ec7225444d9400d30f9027247deb91012fdElliott HughesJDWP::ObjectId Dbg::GetThreadSelfId() { 2039dbe6f4613ae0161b169f4fca8a616b0b393370abMathieu Chartier ScopedObjectAccessUnchecked soa(Thread::Current()); 2040cfaa455374aae0a08c8cb28b5bb306b17866d652Ian Rogers return gRegistry->Add(soa.Self()->GetPeer()); 2041872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2042872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2043475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughesvoid Dbg::SuspendVM() { 204400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers Runtime::Current()->GetThreadList()->SuspendAllForDebugger(); 2045872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2046872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2047872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::ResumeVM() { 2048c61a267e98ed1038b74c33c7740414ced4a27d89Elliott Hughes Runtime::Current()->GetThreadList()->UndoDebuggerSuspensions(); 2049872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2050872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2051221229cb523f849f165fdafbf9785010963715daElliott HughesJDWP::JdwpError Dbg::SuspendThread(JDWP::ObjectId thread_id, bool request_suspension) { 205200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedLocalRef<jobject> peer(Thread::Current()->GetJniEnv(), NULL); 205300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers { 205400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 20552dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers peer.reset(soa.AddLocalReference<jobject>(gRegistry->Get<mirror::Object*>(thread_id))); 205600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 205700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (peer.get() == NULL) { 205800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return JDWP::ERR_THREAD_NOT_ALIVE; 205900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 206000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Suspend thread to build stack trace. 2061f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes bool timed_out; 2062d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers Thread* thread = ThreadList::SuspendThreadByPeer(peer.get(), request_suspension, true, 2063d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers &timed_out); 206400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (thread != NULL) { 206500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return JDWP::ERR_NONE; 2066f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes } else if (timed_out) { 206700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return JDWP::ERR_INTERNAL; 206800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else { 206900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return JDWP::ERR_THREAD_NOT_ALIVE; 20704e235316b4ada4d865c544d9b4ba397139333fa6Elliott Hughes } 2071872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2072872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2073221229cb523f849f165fdafbf9785010963715daElliott Hughesvoid Dbg::ResumeThread(JDWP::ObjectId thread_id) { 207400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 20752dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* peer = gRegistry->Get<mirror::Object*>(thread_id); 2076a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao Thread* thread; 2077a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao { 2078a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 2079a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao thread = Thread::FromManagedThread(soa, peer); 2080a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao } 20814e235316b4ada4d865c544d9b4ba397139333fa6Elliott Hughes if (thread == NULL) { 20824e235316b4ada4d865c544d9b4ba397139333fa6Elliott Hughes LOG(WARNING) << "No such thread for resume: " << peer; 20834e235316b4ada4d865c544d9b4ba397139333fa6Elliott Hughes return; 20844e235316b4ada4d865c544d9b4ba397139333fa6Elliott Hughes } 208500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool needs_resume; 208600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers { 208750b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_); 208800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers needs_resume = thread->GetSuspendCount() > 0; 208900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 209000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (needs_resume) { 2091546b986ecd09c2a498740bd8bf7127e612d94755Elliott Hughes Runtime::Current()->GetThreadList()->Resume(thread, true); 2092546b986ecd09c2a498740bd8bf7127e612d94755Elliott Hughes } 2093872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2094872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2095872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::SuspendSelf() { 2096475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes Runtime::Current()->GetThreadList()->SuspendSelfForDebugger(); 2097872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2098872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 20990399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersstruct GetThisVisitor : public StackVisitor { 21007a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers GetThisVisitor(Thread* thread, Context* context, JDWP::FrameId frame_id) 2101b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 21027a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers : StackVisitor(thread, context), this_object(NULL), frame_id(frame_id) {} 210368fdbd07fc2b8856905e06f3cc945b046c3bfcd3Elliott Hughes 210400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses 210500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // annotalysis. 210600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers virtual bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { 21076e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes if (frame_id != GetFrameId()) { 21080399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers return true; // continue 21090399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } else { 211062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers this_object = GetThisObject(); 211162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return false; 21120399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 211368fdbd07fc2b8856905e06f3cc945b046c3bfcd3Elliott Hughes } 2114dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 21152dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* this_object; 21166e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes JDWP::FrameId frame_id; 21170399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers}; 2118ad3da694bbba88662d1d1bd2cc574d6e3ab6cd42Elliott Hughes 211900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan RogersJDWP::JdwpError Dbg::GetThisObject(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, 212000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JDWP::ObjectId* result) { 212100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 212200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers Thread* thread; 212300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers { 212450b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 2125221229cb523f849f165fdafbf9785010963715daElliott Hughes JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); 2126221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error != JDWP::ERR_NONE) { 2127221229cb523f849f165fdafbf9785010963715daElliott Hughes return error; 212800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 21299e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes if (!IsSuspendedForDebugger(soa, thread)) { 213000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return JDWP::ERR_THREAD_NOT_SUSPENDED; 213100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 21326e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes } 2133caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughes UniquePtr<Context> context(Context::Create()); 21347a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers GetThisVisitor visitor(thread, context.get(), frame_id); 21350399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers visitor.WalkStack(); 21366e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes *result = gRegistry->Add(visitor.this_object); 21376e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes return JDWP::ERR_NONE; 21380399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers} 21390399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers 2140cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien HertzJDWP::JdwpError Dbg::GetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int slot, 2141cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz JDWP::JdwpTag tag, uint8_t* buf, size_t width) { 21420399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers struct GetLocalVisitor : public StackVisitor { 21439837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers GetLocalVisitor(const ScopedObjectAccessUnchecked& soa, Thread* thread, Context* context, 21449837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers JDWP::FrameId frame_id, int slot, JDWP::JdwpTag tag, uint8_t* buf, size_t width) 2145b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 21469837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers : StackVisitor(thread, context), soa_(soa), frame_id_(frame_id), slot_(slot), tag_(tag), 2147cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz buf_(buf), width_(width), error_(JDWP::ERR_NONE) {} 2148ca190666fb11820153f74274c495ba1f913d8a69Ian Rogers 214900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses 215000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // annotalysis. 215100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { 21520399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers if (GetFrameId() != frame_id_) { 21530399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers return true; // Not our frame, carry on. 21540399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 21550399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers // TODO: check that the tag is compatible with the actual type of the slot! 2156cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz // TODO: check slot is valid for this method or return INVALID_SLOT error. 2157ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* m = GetMethod(); 2158cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz if (m->IsNative()) { 2159cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz // We can't read local value from native method. 2160cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz error_ = JDWP::ERR_OPAQUE_FRAME; 2161cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz return false; 2162cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz } 21630399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers uint16_t reg = DemangleSlot(slot_, m); 21640399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers 21650399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers switch (tag_) { 21660399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_BOOLEAN: 21670399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers { 21680399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers CHECK_EQ(width_, 1U); 21692bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers uint32_t intVal = GetVReg(m, reg, kIntVReg); 21700399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers VLOG(jdwp) << "get boolean local " << reg << " = " << intVal; 21710399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers JDWP::Set1(buf_+1, intVal != 0); 21720399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 21730399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers break; 21740399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_BYTE: 21750399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers { 21760399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers CHECK_EQ(width_, 1U); 21772bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers uint32_t intVal = GetVReg(m, reg, kIntVReg); 21780399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers VLOG(jdwp) << "get byte local " << reg << " = " << intVal; 21790399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers JDWP::Set1(buf_+1, intVal); 21800399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 21810399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers break; 21820399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_SHORT: 21830399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_CHAR: 21840399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers { 21850399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers CHECK_EQ(width_, 2U); 21862bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers uint32_t intVal = GetVReg(m, reg, kIntVReg); 21870399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers VLOG(jdwp) << "get short/char local " << reg << " = " << intVal; 21880399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers JDWP::Set2BE(buf_+1, intVal); 21890399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 21900399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers break; 21910399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_INT: 21922bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers { 21932bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers CHECK_EQ(width_, 4U); 21942bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers uint32_t intVal = GetVReg(m, reg, kIntVReg); 21952bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers VLOG(jdwp) << "get int local " << reg << " = " << intVal; 21962bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers JDWP::Set4BE(buf_+1, intVal); 21972bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers } 21982bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers break; 21990399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_FLOAT: 22000399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers { 22010399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers CHECK_EQ(width_, 4U); 22022bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers uint32_t intVal = GetVReg(m, reg, kFloatVReg); 22030399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers VLOG(jdwp) << "get int/float local " << reg << " = " << intVal; 22040399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers JDWP::Set4BE(buf_+1, intVal); 22050399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 22060399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers break; 22070399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_ARRAY: 22080399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers { 22090399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers CHECK_EQ(width_, sizeof(JDWP::ObjectId)); 22102dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* o = reinterpret_cast<mirror::Object*>(GetVReg(m, reg, kReferenceVReg)); 22110399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers VLOG(jdwp) << "get array local " << reg << " = " << o; 2212590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) { 22130399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers LOG(FATAL) << "Register " << reg << " expected to hold array: " << o; 22140399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 22150399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers JDWP::SetObjectId(buf_+1, gRegistry->Add(o)); 22160399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 22170399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers break; 22180399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_CLASS_LOADER: 22190399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_CLASS_OBJECT: 22200399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_OBJECT: 22210399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_STRING: 22220399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_THREAD: 22230399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_THREAD_GROUP: 22240399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers { 22250399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers CHECK_EQ(width_, sizeof(JDWP::ObjectId)); 22262dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* o = reinterpret_cast<mirror::Object*>(GetVReg(m, reg, kReferenceVReg)); 22270399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers VLOG(jdwp) << "get object local " << reg << " = " << o; 2228590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) { 22290399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers LOG(FATAL) << "Register " << reg << " expected to hold object: " << o; 22300399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 22319837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers tag_ = TagFromObject(soa_, o); 22320399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers JDWP::SetObjectId(buf_+1, gRegistry->Add(o)); 22330399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 22340399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers break; 22350399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_DOUBLE: 22362bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers { 22372bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers CHECK_EQ(width_, 8U); 22382bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers uint32_t lo = GetVReg(m, reg, kDoubleLoVReg); 22392bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers uint64_t hi = GetVReg(m, reg + 1, kDoubleHiVReg); 22402bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers uint64_t longVal = (hi << 32) | lo; 22412bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers VLOG(jdwp) << "get double/long local " << hi << ":" << lo << " = " << longVal; 22422bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers JDWP::Set8BE(buf_+1, longVal); 22432bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers } 22442bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers break; 22450399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_LONG: 22460399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers { 22470399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers CHECK_EQ(width_, 8U); 22482bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers uint32_t lo = GetVReg(m, reg, kLongLoVReg); 22492bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers uint64_t hi = GetVReg(m, reg + 1, kLongHiVReg); 22500399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers uint64_t longVal = (hi << 32) | lo; 22510399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers VLOG(jdwp) << "get double/long local " << hi << ":" << lo << " = " << longVal; 22520399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers JDWP::Set8BE(buf_+1, longVal); 22530399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 22540399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers break; 22550399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers default: 22560399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers LOG(FATAL) << "Unknown tag " << tag_; 22570399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers break; 22580399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 2259ad3da694bbba88662d1d1bd2cc574d6e3ab6cd42Elliott Hughes 22600399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers // Prepend tag, which may have been updated. 22610399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers JDWP::Set1(buf_, tag_); 22620399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers return false; 22630399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 22649837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers const ScopedObjectAccessUnchecked& soa_; 22650399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers const JDWP::FrameId frame_id_; 22660399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers const int slot_; 22670399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers JDWP::JdwpTag tag_; 22680399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers uint8_t* const buf_; 22690399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers const size_t width_; 2270cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz JDWP::JdwpError error_; 22710399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers }; 227200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 227300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 2274a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 2275221229cb523f849f165fdafbf9785010963715daElliott Hughes Thread* thread; 2276221229cb523f849f165fdafbf9785010963715daElliott Hughes JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); 2277221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error != JDWP::ERR_NONE) { 2278cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz return error; 2279221229cb523f849f165fdafbf9785010963715daElliott Hughes } 2280cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz // TODO check thread is suspended by the debugger ? 22810399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers UniquePtr<Context> context(Context::Create()); 22829837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers GetLocalVisitor visitor(soa, thread, context.get(), frame_id, slot, tag, buf, width); 22830399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers visitor.WalkStack(); 2284cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz return visitor.error_; 22850399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers} 22860399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers 2287cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien HertzJDWP::JdwpError Dbg::SetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int slot, 2288cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz JDWP::JdwpTag tag, uint64_t value, size_t width) { 22890399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers struct SetLocalVisitor : public StackVisitor { 22907a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers SetLocalVisitor(Thread* thread, Context* context, 22910399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers JDWP::FrameId frame_id, int slot, JDWP::JdwpTag tag, uint64_t value, 2292ca190666fb11820153f74274c495ba1f913d8a69Ian Rogers size_t width) 2293b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 22947a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers : StackVisitor(thread, context), 2295cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz frame_id_(frame_id), slot_(slot), tag_(tag), value_(value), width_(width), 2296cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz error_(JDWP::ERR_NONE) {} 2297ca190666fb11820153f74274c495ba1f913d8a69Ian Rogers 229800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses 229900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // annotalysis. 230000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { 23010399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers if (GetFrameId() != frame_id_) { 23020399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers return true; // Not our frame, carry on. 2303ad3da694bbba88662d1d1bd2cc574d6e3ab6cd42Elliott Hughes } 23040399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers // TODO: check that the tag is compatible with the actual type of the slot! 2305cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz // TODO: check slot is valid for this method or return INVALID_SLOT error. 2306ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* m = GetMethod(); 2307cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz if (m->IsNative()) { 2308cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz // We can't read local value from native method. 2309cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz error_ = JDWP::ERR_OPAQUE_FRAME; 2310cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz return false; 2311cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz } 23120399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers uint16_t reg = DemangleSlot(slot_, m); 23130399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers 23140399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers switch (tag_) { 23150399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_BOOLEAN: 23160399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_BYTE: 23170399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers CHECK_EQ(width_, 1U); 23182bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers SetVReg(m, reg, static_cast<uint32_t>(value_), kIntVReg); 23190399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers break; 23200399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_SHORT: 23210399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_CHAR: 23220399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers CHECK_EQ(width_, 2U); 23232bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers SetVReg(m, reg, static_cast<uint32_t>(value_), kIntVReg); 23240399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers break; 23250399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_INT: 23262bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers CHECK_EQ(width_, 4U); 23272bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers SetVReg(m, reg, static_cast<uint32_t>(value_), kIntVReg); 23282bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers break; 23290399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_FLOAT: 23300399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers CHECK_EQ(width_, 4U); 23312bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers SetVReg(m, reg, static_cast<uint32_t>(value_), kFloatVReg); 23320399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers break; 23330399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_ARRAY: 23340399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_OBJECT: 23350399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_STRING: 23360399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers { 23370399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers CHECK_EQ(width_, sizeof(JDWP::ObjectId)); 23382dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(static_cast<JDWP::ObjectId>(value_)); 233964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (o == ObjectRegistry::kInvalidObject) { 23400399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers UNIMPLEMENTED(FATAL) << "return an error code when given an invalid object to store"; 23410399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 23422bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers SetVReg(m, reg, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(o)), kReferenceVReg); 23430399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 23440399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers break; 23450399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_DOUBLE: 23462bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers CHECK_EQ(width_, 8U); 23472bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers SetVReg(m, reg, static_cast<uint32_t>(value_), kDoubleLoVReg); 23482bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers SetVReg(m, reg + 1, static_cast<uint32_t>(value_ >> 32), kDoubleHiVReg); 23492bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers break; 23500399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers case JDWP::JT_LONG: 23510399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers CHECK_EQ(width_, 8U); 23522bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers SetVReg(m, reg, static_cast<uint32_t>(value_), kLongLoVReg); 23532bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers SetVReg(m, reg + 1, static_cast<uint32_t>(value_ >> 32), kLongHiVReg); 23540399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers break; 23550399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers default: 23560399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers LOG(FATAL) << "Unknown tag " << tag_; 23570399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers break; 23580399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 23590399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers return false; 2360cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes } 23610399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers 23620399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers const JDWP::FrameId frame_id_; 23630399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers const int slot_; 23640399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers const JDWP::JdwpTag tag_; 23650399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers const uint64_t value_; 23660399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers const size_t width_; 2367cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz JDWP::JdwpError error_; 23680399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers }; 236900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 237000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 2371a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 2372221229cb523f849f165fdafbf9785010963715daElliott Hughes Thread* thread; 2373221229cb523f849f165fdafbf9785010963715daElliott Hughes JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); 2374221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error != JDWP::ERR_NONE) { 2375cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz return error; 2376221229cb523f849f165fdafbf9785010963715daElliott Hughes } 2377cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz // TODO check thread is suspended by the debugger ? 237808fc03ae5dded4adc9b45b7014a4b9dfedbe95a6Elliott Hughes UniquePtr<Context> context(Context::Create()); 23797a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers SetLocalVisitor visitor(thread, context.get(), frame_id, slot, tag, value, width); 23800399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers visitor.WalkStack(); 2381cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz return visitor.error_; 2382872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2383872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2384ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersvoid Dbg::PostLocationEvent(mirror::ArtMethod* m, int dex_pc, mirror::Object* this_object, 2385579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao int event_flags, const JValue* return_value) { 238691bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes JDWP::JdwpLocation location; 2387cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz SetLocation(location, m, dex_pc); 238891bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes 238964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes // If 'this_object' isn't already in the registry, we know that we're not looking for it, 239064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes // so there's no point adding it to the registry and burning through ids. 239164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes JDWP::ObjectId this_id = 0; 239264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (gRegistry->Contains(this_object)) { 239364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes this_id = gRegistry->Add(this_object); 239491bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes } 2395579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao gJdwpState->PostLocationEvent(&location, this_id, event_flags, return_value); 2396872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2397872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 239862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Dbg::PostException(Thread* thread, const ThrowLocation& throw_location, 2399ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* catch_method, 240064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes uint32_t catch_dex_pc, mirror::Throwable* exception_object) { 2401c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes if (!IsDebuggerActive()) { 24020ad5bb8ea378a223eb6eaf89e0be2823c6f87c0eIan Rogers return; 24030ad5bb8ea378a223eb6eaf89e0be2823c6f87c0eIan Rogers } 24044740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes 240562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers JDWP::JdwpLocation jdwp_throw_location; 240662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers SetLocation(jdwp_throw_location, throw_location.GetMethod(), throw_location.GetDexPc()); 2407d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes JDWP::JdwpLocation catch_location; 2408caf7654a0e6c76c7489970b1a246fccf220f9982Elliott Hughes SetLocation(catch_location, catch_method, catch_dex_pc); 2409d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 2410d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes // We need 'this' for InstanceOnly filters. 241162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers JDWP::ObjectId this_id = gRegistry->Add(throw_location.GetThis()); 241264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes JDWP::ObjectId exception_id = gRegistry->Add(exception_object); 241364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes JDWP::RefTypeId exception_class_id = gRegistry->AddRefType(exception_object->GetClass()); 2414d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 241562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers gJdwpState->PostException(&jdwp_throw_location, exception_id, exception_class_id, &catch_location, 241662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers this_id); 2417872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2418872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 24192dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersvoid Dbg::PostClassPrepare(mirror::Class* c) { 2420c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes if (!IsDebuggerActive()) { 24214740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes return; 24224740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes } 24234740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes 24243d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes // OLD-TODO - we currently always send both "verified" and "prepared" since 24254740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes // debuggers seem to like that. There might be some advantage to honesty, 24264740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes // since the class may not yet be verified. 24274740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes int state = JDWP::CS_VERIFIED | JDWP::CS_PREPARED; 24284740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes JDWP::JdwpTypeTag tag = c->IsInterface() ? JDWP::TT_INTERFACE : JDWP::TT_CLASS; 2429fc0e94bed3f88ed7e50854fd8dfaf5dcb345250fIan Rogers gJdwpState->PostClassPrepare(tag, gRegistry->Add(c), 2430dfb325e0ddd746cd8f7c2e3723b3a573eb7cc111Ian Rogers ClassHelper(c).GetDescriptor(), state); 2431872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2432872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 243362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Dbg::UpdateDebugger(Thread* thread, mirror::Object* this_object, 2434ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::ArtMethod* m, uint32_t dex_pc) { 243562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (!IsDebuggerActive() || dex_pc == static_cast<uint32_t>(-2) /* fake method exit */) { 24362aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes return; 243791bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes } 243891bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes 24392aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes int event_flags = 0; 24402aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes 24418696433d1b3d8ba15288483b777edd888de69135Elliott Hughes if (IsBreakpoint(m, dex_pc)) { 24428696433d1b3d8ba15288483b777edd888de69135Elliott Hughes event_flags |= kBreakpoint; 244391bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes } 244491bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes 244561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // If the debugger is single-stepping one of our threads, check to 244661b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // see if we're that thread and we've reached a step point. 244761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz const SingleStepControl* single_step_control = thread->GetSingleStepControl(); 244861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz DCHECK(single_step_control != nullptr); 244961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz if (single_step_control->is_active) { 245061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz CHECK(!m->IsNative()); 245161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz if (single_step_control->step_depth == JDWP::SD_INTO) { 245261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // Step into method calls. We break when the line number 245361b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // or method pointer changes. If we're in SS_MIN mode, we 245461b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // always stop. 245561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz if (single_step_control->method != m) { 245661b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz event_flags |= kSingleStep; 245761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz VLOG(jdwp) << "SS new method"; 245861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz } else if (single_step_control->step_size == JDWP::SS_MIN) { 245961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz event_flags |= kSingleStep; 246061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz VLOG(jdwp) << "SS new instruction"; 246161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz } else if (single_step_control->dex_pcs.find(dex_pc) == single_step_control->dex_pcs.end()) { 246261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz event_flags |= kSingleStep; 246361b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz VLOG(jdwp) << "SS new line"; 246461b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz } 246561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz } else if (single_step_control->step_depth == JDWP::SD_OVER) { 246661b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // Step over method calls. We break when the line number is 246761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // different and the frame depth is <= the original frame 246861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // depth. (We can't just compare on the method, because we 246961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // might get unrolled past it by an exception, and it's tricky 247061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // to identify recursion.) 247161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz 247261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz int stack_depth = GetStackDepth(thread); 247361b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz 247461b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz if (stack_depth < single_step_control->stack_depth) { 247561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // Popped up one or more frames, always trigger. 247661b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz event_flags |= kSingleStep; 247761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz VLOG(jdwp) << "SS method pop"; 247861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz } else if (stack_depth == single_step_control->stack_depth) { 247961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // Same depth, see if we moved. 248061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz if (single_step_control->step_size == JDWP::SS_MIN) { 24818696433d1b3d8ba15288483b777edd888de69135Elliott Hughes event_flags |= kSingleStep; 24828696433d1b3d8ba15288483b777edd888de69135Elliott Hughes VLOG(jdwp) << "SS new instruction"; 248361b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz } else if (single_step_control->dex_pcs.find(dex_pc) == single_step_control->dex_pcs.end()) { 24842435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes event_flags |= kSingleStep; 24852435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes VLOG(jdwp) << "SS new line"; 248691bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes } 248761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz } 248861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz } else { 248961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz CHECK_EQ(single_step_control->step_depth, JDWP::SD_OUT); 249061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // Return from the current method. We break when the frame 249161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // depth pops up. 249261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz 249361b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // This differs from the "method exit" break in that it stops 249461b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // with the PC at the next instruction in the returned-to 249561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // function, rather than the end of the returning function. 249661b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz 249761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz int stack_depth = GetStackDepth(thread); 249861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz if (stack_depth < single_step_control->stack_depth) { 249961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz event_flags |= kSingleStep; 250061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz VLOG(jdwp) << "SS method pop"; 25018696433d1b3d8ba15288483b777edd888de69135Elliott Hughes } 250291bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes } 250391bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes } 250491bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes 250591bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes // If there's something interesting going on, see if it matches one 250691bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes // of the debugger filters. 250791bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes if (event_flags != 0) { 2508579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao Dbg::PostLocationEvent(m, dex_pc, this_object, event_flags, nullptr); 250991bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes } 251091bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes} 251191bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes 2512138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertzstatic void ProcessDeoptimizationRequests() 2513138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz LOCKS_EXCLUDED(Locks::deoptimization_lock_) 2514138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_) { 2515138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz Locks::mutator_lock_->AssertExclusiveHeld(Thread::Current()); 2516138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_); 2517138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); 2518138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz for (const MethodInstrumentationRequest& request : gDeoptimizationRequests) { 2519138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz mirror::ArtMethod* const method = request.method; 2520138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz if (method != nullptr) { 2521138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz // Selective deoptimization. 2522138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz if (request.deoptimize) { 2523138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz VLOG(jdwp) << "Deoptimize method " << PrettyMethod(method); 2524138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz instrumentation->Deoptimize(method); 2525138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } else { 2526138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz VLOG(jdwp) << "Undeoptimize method " << PrettyMethod(method); 2527138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz instrumentation->Undeoptimize(method); 2528138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 2529138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } else { 2530138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz // Full deoptimization. 2531138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz if (request.deoptimize) { 2532138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz VLOG(jdwp) << "Deoptimize the world"; 2533138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz instrumentation->DeoptimizeEverything(); 2534138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } else { 2535138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz VLOG(jdwp) << "Undeoptimize the world"; 2536138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz instrumentation->UndeoptimizeEverything(); 2537138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 2538138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 2539138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 2540138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz gDeoptimizationRequests.clear(); 2541138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz} 2542138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 2543138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz// Process deoptimization requests after suspending all mutator threads. 2544138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertzvoid Dbg::ManageDeoptimization() { 2545138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz Thread* const self = Thread::Current(); 2546138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz { 2547138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz // Avoid suspend/resume if there is no pending request. 2548138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz MutexLock mu(self, *Locks::deoptimization_lock_); 2549138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz if (gDeoptimizationRequests.empty()) { 2550138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz return; 2551138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 2552138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 2553138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz CHECK_EQ(self->GetState(), kRunnable); 2554138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz self->TransitionFromRunnableToSuspended(kWaitingForDeoptimization); 2555138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz // We need to suspend mutator threads first. 2556138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz Runtime* const runtime = Runtime::Current(); 2557138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz runtime->GetThreadList()->SuspendAll(); 2558138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz const ThreadState old_state = self->SetStateUnsafe(kRunnable); 2559138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz ProcessDeoptimizationRequests(); 2560138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz CHECK_EQ(self->SetStateUnsafe(old_state), kRunnable); 2561138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz runtime->GetThreadList()->ResumeAll(); 2562138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz self->TransitionFromSuspendedToRunnable(); 2563138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz} 2564138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 2565138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz// Enable full deoptimization. 2566138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertzvoid Dbg::EnableFullDeoptimization() { 2567138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_); 2568138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz VLOG(jdwp) << "Request full deoptimization"; 2569138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz gDeoptimizationRequests.push_back(MethodInstrumentationRequest(true, nullptr)); 2570138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz} 2571138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 2572138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz// Disable full deoptimization. 2573138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertzvoid Dbg::DisableFullDeoptimization() { 2574138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_); 2575138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz VLOG(jdwp) << "Request full undeoptimization"; 2576138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz gDeoptimizationRequests.push_back(MethodInstrumentationRequest(false, nullptr)); 2577138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz} 2578138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 25798696433d1b3d8ba15288483b777edd888de69135Elliott Hughesvoid Dbg::WatchLocation(const JDWP::JdwpLocation* location) { 2580138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz bool need_deoptimization = true; 2581ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* m = FromMethodId(location->method_id); 2582138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz { 2583138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_); 2584138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 2585138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz // If there is no breakpoint on this method yet, we need to deoptimize it. 2586138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz for (const Breakpoint& breakpoint : gBreakpoints) { 2587138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz if (breakpoint.method == m) { 2588138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz // We already set a breakpoint on this method, hence we deoptimized it. 2589138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz DCHECK(Runtime::Current()->GetInstrumentation()->IsDeoptimized(m)); 2590138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz need_deoptimization = false; 2591138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz break; 2592138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 2593138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 2594138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 2595138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz gBreakpoints.push_back(Breakpoint(m, location->dex_pc)); 2596138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz VLOG(jdwp) << "Set breakpoint #" << (gBreakpoints.size() - 1) << ": " << gBreakpoints[gBreakpoints.size() - 1]; 2597138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 2598138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 2599138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz if (need_deoptimization) { 2600138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz // Request its deoptimization. This will be done after updating the JDWP event list. 2601138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_); 2602138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz gDeoptimizationRequests.push_back(MethodInstrumentationRequest(true, m)); 2603138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz VLOG(jdwp) << "Request deoptimization of " << PrettyMethod(m); 2604138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 2605872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2606872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 26078696433d1b3d8ba15288483b777edd888de69135Elliott Hughesvoid Dbg::UnwatchLocation(const JDWP::JdwpLocation* location) { 2608138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz bool can_undeoptimize = true; 2609ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* m = FromMethodId(location->method_id); 2610138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz DCHECK(Runtime::Current()->GetInstrumentation()->IsDeoptimized(m)); 2611138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz { 2612138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz MutexLock mu(Thread::Current(), *Locks::breakpoint_lock_); 2613138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz for (size_t i = 0, e = gBreakpoints.size(); i < e; ++i) { 2614138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz if (gBreakpoints[i].method == m && gBreakpoints[i].dex_pc == location->dex_pc) { 2615138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz VLOG(jdwp) << "Removed breakpoint #" << i << ": " << gBreakpoints[i]; 2616138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz gBreakpoints.erase(gBreakpoints.begin() + i); 2617138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz break; 2618138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 26198696433d1b3d8ba15288483b777edd888de69135Elliott Hughes } 2620138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 2621138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz // If there is no breakpoint on this method, we can undeoptimize it. 2622138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz for (const Breakpoint& breakpoint : gBreakpoints) { 2623138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz if (breakpoint.method == m) { 2624138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz can_undeoptimize = false; 2625138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz break; 2626138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 2627138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 2628138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 2629138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 2630138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz if (can_undeoptimize) { 2631138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz // Request its undeoptimization. This will be done after updating the JDWP event list. 2632138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_); 2633138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz gDeoptimizationRequests.push_back(MethodInstrumentationRequest(false, m)); 2634138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz VLOG(jdwp) << "Request undeoptimization of " << PrettyMethod(m); 26358696433d1b3d8ba15288483b777edd888de69135Elliott Hughes } 2636872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2637872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2638449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao// Scoped utility class to suspend a thread so that we may do tasks such as walk its stack. Doesn't 2639449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao// cause suspension if the thread is the current thread. 2640449db33fafa29578df60e8a323f78d5eb6247e76Jeff Haoclass ScopedThreadSuspension { 2641449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao public: 264233e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogers ScopedThreadSuspension(Thread* self, JDWP::ObjectId thread_id) 264352d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz LOCKS_EXCLUDED(Locks::thread_list_lock_) 264433e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : 2645449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao thread_(NULL), 2646449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao error_(JDWP::ERR_NONE), 2647449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao self_suspend_(false), 264833e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogers other_suspend_(false) { 2649449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao ScopedObjectAccessUnchecked soa(self); 2650449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao { 2651449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 2652449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao error_ = DecodeThread(soa, thread_id, thread_); 2653449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } 2654449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao if (error_ == JDWP::ERR_NONE) { 2655449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao if (thread_ == soa.Self()) { 2656449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao self_suspend_ = true; 2657449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } else { 2658449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao soa.Self()->TransitionFromRunnableToSuspended(kWaitingForDebuggerSuspension); 2659449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao jobject thread_peer = gRegistry->GetJObject(thread_id); 2660449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao bool timed_out; 2661d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers Thread* suspended_thread = ThreadList::SuspendThreadByPeer(thread_peer, true, true, 2662d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers &timed_out); 2663449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao CHECK_EQ(soa.Self()->TransitionFromSuspendedToRunnable(), kWaitingForDebuggerSuspension); 2664449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao if (suspended_thread == NULL) { 2665449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao // Thread terminated from under us while suspending. 2666449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao error_ = JDWP::ERR_INVALID_THREAD; 2667449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } else { 2668449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao CHECK_EQ(suspended_thread, thread_); 2669449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao other_suspend_ = true; 2670449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } 2671449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } 2672449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } 2673449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } 2674449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao 2675449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao Thread* GetThread() const { 2676449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao return thread_; 2677449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } 2678449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao 2679449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao JDWP::JdwpError GetError() const { 2680449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao return error_; 2681449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } 2682449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao 2683449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao ~ScopedThreadSuspension() { 2684449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao if (other_suspend_) { 2685449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao Runtime::Current()->GetThreadList()->Resume(thread_, true); 2686449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } 2687449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } 2688449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao 2689449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao private: 2690449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao Thread* thread_; 2691449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao JDWP::JdwpError error_; 2692449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao bool self_suspend_; 2693449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao bool other_suspend_; 2694449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao}; 2695449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao 2696221229cb523f849f165fdafbf9785010963715daElliott HughesJDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize step_size, 269700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JDWP::JdwpStepDepth step_depth) { 2698449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao Thread* self = Thread::Current(); 2699449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao ScopedThreadSuspension sts(self, thread_id); 2700449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao if (sts.GetError() != JDWP::ERR_NONE) { 2701449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao return sts.GetError(); 27022435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 27038696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 27042435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // 27052435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // Work out what Method* we're in, the current line number, and how deep the stack currently 27062435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // is for step-out. 27072435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // 27082435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 27090399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers struct SingleStepStackVisitor : public StackVisitor { 271061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz explicit SingleStepStackVisitor(Thread* thread, SingleStepControl* single_step_control, 271161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz int32_t* line_number) 2712b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 271361b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz : StackVisitor(thread, NULL), single_step_control_(single_step_control), 271461b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz line_number_(line_number) { 271561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz DCHECK_EQ(single_step_control_, thread->GetSingleStepControl()); 271661b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz single_step_control_->method = NULL; 271761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz single_step_control_->stack_depth = 0; 27188696433d1b3d8ba15288483b777edd888de69135Elliott Hughes } 2719ca190666fb11820153f74274c495ba1f913d8a69Ian Rogers 272000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses 272100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // annotalysis. 272200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { 272361b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz mirror::ArtMethod* m = GetMethod(); 27240399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers if (!m->IsRuntimeMethod()) { 272561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz ++single_step_control_->stack_depth; 272661b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz if (single_step_control_->method == NULL) { 2727ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::DexCache* dex_cache = m->GetDeclaringClass()->GetDexCache(); 272861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz single_step_control_->method = m; 272961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz *line_number_ = -1; 27302435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes if (dex_cache != NULL) { 27314445a7e3398a6143939168097a3aa275b734504dIan Rogers const DexFile& dex_file = *dex_cache->GetDexFile(); 273261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz *line_number_ = dex_file.GetLineNumFromPC(m, GetDexPc()); 27332435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 27348696433d1b3d8ba15288483b777edd888de69135Elliott Hughes } 27358696433d1b3d8ba15288483b777edd888de69135Elliott Hughes } 2736530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return true; 27378696433d1b3d8ba15288483b777edd888de69135Elliott Hughes } 273861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz 273961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz SingleStepControl* const single_step_control_; 274061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz int32_t* const line_number_; 27418696433d1b3d8ba15288483b777edd888de69135Elliott Hughes }; 2742449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao 274361b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz Thread* const thread = sts.GetThread(); 274461b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz SingleStepControl* const single_step_control = thread->GetSingleStepControl(); 274561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz DCHECK(single_step_control != nullptr); 274661b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz int32_t line_number = -1; 274761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz SingleStepStackVisitor visitor(thread, single_step_control, &line_number); 27480399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers visitor.WalkStack(); 27498696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 27502435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // 27512435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // Find the dex_pc values that correspond to the current line, for line-based single-stepping. 27522435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // 27532435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 27542435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes struct DebugCallbackContext { 275561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz explicit DebugCallbackContext(SingleStepControl* single_step_control, int32_t line_number) 275661b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz : single_step_control_(single_step_control), line_number_(line_number), 275761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz last_pc_valid(false), last_pc(0) { 27582435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 27592435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 276061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz static bool Callback(void* raw_context, uint32_t address, uint32_t line_number) { 27612435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes DebugCallbackContext* context = reinterpret_cast<DebugCallbackContext*>(raw_context); 276261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz if (static_cast<int32_t>(line_number) == context->line_number_) { 27632435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes if (!context->last_pc_valid) { 27642435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // Everything from this address until the next line change is ours. 27652435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes context->last_pc = address; 27662435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes context->last_pc_valid = true; 27672435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 27682435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // Otherwise, if we're already in a valid range for this line, 27692435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // just keep going (shouldn't really happen)... 27707934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (context->last_pc_valid) { // and the line number is new 27712435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // Add everything from the last entry up until here to the set 27722435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes for (uint32_t dex_pc = context->last_pc; dex_pc < address; ++dex_pc) { 277361b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz context->single_step_control_->dex_pcs.insert(dex_pc); 27742435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 27752435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes context->last_pc_valid = false; 27762435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 27777934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom return false; // There may be multiple entries for any given line. 27782435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 27792435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 278061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz ~DebugCallbackContext() { 27812435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // If the line number was the last in the position table... 27822435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes if (last_pc_valid) { 278361b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz size_t end = MethodHelper(single_step_control_->method).GetCodeItem()->insns_size_in_code_units_; 27842435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes for (uint32_t dex_pc = last_pc; dex_pc < end; ++dex_pc) { 278561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz single_step_control_->dex_pcs.insert(dex_pc); 27862435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 27872435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 27882435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 27892435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 279061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz SingleStepControl* const single_step_control_; 279161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz const int32_t line_number_; 27922435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes bool last_pc_valid; 27932435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes uint32_t last_pc; 27942435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes }; 279561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz single_step_control->dex_pcs.clear(); 2796ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::ArtMethod* m = single_step_control->method; 279761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz if (!m->IsNative()) { 279861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz DebugCallbackContext context(single_step_control, line_number); 27993e2e1a2380e7b2ce402640ea4f6a177c06bd19a2Elliott Hughes MethodHelper mh(m); 28003e2e1a2380e7b2ce402640ea4f6a177c06bd19a2Elliott Hughes mh.GetDexFile().DecodeDebugInfo(mh.GetCodeItem(), m->IsStatic(), m->GetDexMethodIndex(), 28013e2e1a2380e7b2ce402640ea4f6a177c06bd19a2Elliott Hughes DebugCallbackContext::Callback, NULL, &context); 28023e2e1a2380e7b2ce402640ea4f6a177c06bd19a2Elliott Hughes } 28032435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 28042435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // 28052435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // Everything else... 28062435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // 28072435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 280861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz single_step_control->step_size = step_size; 280961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz single_step_control->step_depth = step_depth; 281061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz single_step_control->is_active = true; 28118696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 28122435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes if (VLOG_IS_ON(jdwp)) { 281361b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz VLOG(jdwp) << "Single-step thread: " << *thread; 281461b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz VLOG(jdwp) << "Single-step step size: " << single_step_control->step_size; 281561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz VLOG(jdwp) << "Single-step step depth: " << single_step_control->step_depth; 281661b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz VLOG(jdwp) << "Single-step current method: " << PrettyMethod(single_step_control->method); 281761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz VLOG(jdwp) << "Single-step current line: " << line_number; 281861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz VLOG(jdwp) << "Single-step current stack depth: " << single_step_control->stack_depth; 28192435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes VLOG(jdwp) << "Single-step dex_pc values:"; 282061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz for (std::set<uint32_t>::iterator it = single_step_control->dex_pcs.begin(); it != single_step_control->dex_pcs.end(); ++it) { 2821229feb7a09317919ee51c06d1c3e715cea25da75Elliott Hughes VLOG(jdwp) << StringPrintf(" %#x", *it); 28222435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 28232435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 28242435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 28252435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes return JDWP::ERR_NONE; 2826872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2827872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 282861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertzvoid Dbg::UnconfigureStep(JDWP::ObjectId thread_id) { 282961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz ScopedObjectAccessUnchecked soa(Thread::Current()); 283061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 283161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz Thread* thread; 283261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz JDWP::JdwpError error = DecodeThread(soa, thread_id, thread); 283387118ed6f3f99e7df33214c277cf200a7b9a7499Sebastien Hertz if (error == JDWP::ERR_NONE) { 283461b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz SingleStepControl* single_step_control = thread->GetSingleStepControl(); 283561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz DCHECK(single_step_control != nullptr); 283661b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz single_step_control->is_active = false; 283761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz single_step_control->dex_pcs.clear(); 283861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz } 2839872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2840872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 284145651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughesstatic char JdwpTagToShortyChar(JDWP::JdwpTag tag) { 284245651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes switch (tag) { 284345651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes default: 284445651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes LOG(FATAL) << "unknown JDWP tag: " << PrintableChar(tag); 284545651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes 284645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes // Primitives. 284745651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_BYTE: return 'B'; 284845651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_CHAR: return 'C'; 284945651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_FLOAT: return 'F'; 285045651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_DOUBLE: return 'D'; 285145651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_INT: return 'I'; 285245651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_LONG: return 'J'; 285345651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_SHORT: return 'S'; 285445651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_VOID: return 'V'; 285545651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_BOOLEAN: return 'Z'; 285645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes 285745651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes // Reference types. 285845651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_ARRAY: 285945651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_OBJECT: 286045651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_STRING: 286145651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_THREAD: 286245651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_THREAD_GROUP: 286345651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_CLASS_LOADER: 286445651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_CLASS_OBJECT: 286545651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes return 'L'; 286645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } 286745651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes} 286845651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes 286988d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::InvokeMethod(JDWP::ObjectId thread_id, JDWP::ObjectId object_id, 287088d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes JDWP::RefTypeId class_id, JDWP::MethodId method_id, 287100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers uint32_t arg_count, uint64_t* arg_values, 287200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JDWP::JdwpTag* arg_types, uint32_t options, 287300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JDWP::JdwpTag* pResultTag, uint64_t* pResultValue, 287400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JDWP::ObjectId* pExceptionId) { 2875d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes ThreadList* thread_list = Runtime::Current()->GetThreadList(); 2876d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 2877d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes Thread* targetThread = NULL; 2878d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes DebugInvokeReq* req = NULL; 287900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers Thread* self = Thread::Current(); 2880d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes { 288100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(self); 288250b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 2883221229cb523f849f165fdafbf9785010963715daElliott Hughes JDWP::JdwpError error = DecodeThread(soa, thread_id, targetThread); 2884221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error != JDWP::ERR_NONE) { 2885221229cb523f849f165fdafbf9785010963715daElliott Hughes LOG(ERROR) << "InvokeMethod request for invalid thread id " << thread_id; 2886221229cb523f849f165fdafbf9785010963715daElliott Hughes return error; 2887d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 2888d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes req = targetThread->GetInvokeReq(); 2889d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes if (!req->ready) { 2890d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes LOG(ERROR) << "InvokeMethod request for thread not stopped by event: " << *targetThread; 2891d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes return JDWP::ERR_INVALID_THREAD; 2892d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 2893d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 2894d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes /* 2895d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * We currently have a bug where we don't successfully resume the 2896d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * target thread if the suspend count is too deep. We're expected to 2897d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * require one "resume" for each "suspend", but when asked to execute 2898d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * a method we have to resume fully and then re-suspend it back to the 2899d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * same level. (The easiest way to cause this is to type "suspend" 2900d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * multiple times in jdb.) 2901d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * 2902d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * It's unclear what this means when the event specifies "resume all" 2903d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * and some threads are suspended more deeply than others. This is 2904d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * a rare problem, so for now we just prevent it from hanging forever 2905d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * by rejecting the method invocation request. Without this, we will 2906d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * be stuck waiting on a suspended thread. 2907d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes */ 290800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers int suspend_count; 290900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers { 291050b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_); 291100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers suspend_count = targetThread->GetSuspendCount(); 291200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 2913d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes if (suspend_count > 1) { 2914d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes LOG(ERROR) << *targetThread << " suspend count too deep for method invocation: " << suspend_count; 29157934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom return JDWP::ERR_THREAD_SUSPENDED; // Probably not expected here. 2916d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 2917d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 29183f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes JDWP::JdwpError status; 29192dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* receiver = gRegistry->Get<mirror::Object*>(object_id); 292064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (receiver == ObjectRegistry::kInvalidObject) { 29213f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 29223f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes } 292345651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes 29242dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* thread = gRegistry->Get<mirror::Object*>(thread_id); 292564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (thread == ObjectRegistry::kInvalidObject) { 29263f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 29273f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes } 292845651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes // TODO: check that 'thread' is actually a java.lang.Thread! 292945651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes 29302dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = DecodeClass(class_id, status); 293145651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes if (c == NULL) { 29323f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes return status; 29333f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes } 293445651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes 2935ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* m = FromMethodId(method_id); 293645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes if (m->IsStatic() != (receiver == NULL)) { 293745651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes return JDWP::ERR_INVALID_METHODID; 293845651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } 293945651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes if (m->IsStatic()) { 294045651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes if (m->GetDeclaringClass() != c) { 294145651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes return JDWP::ERR_INVALID_METHODID; 294245651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } 294345651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } else { 294445651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes if (!m->GetDeclaringClass()->IsAssignableFrom(c)) { 294545651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes return JDWP::ERR_INVALID_METHODID; 294645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } 294745651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } 294845651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes 294945651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes // Check the argument list matches the method. 295045651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes MethodHelper mh(m); 295145651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes if (mh.GetShortyLength() - 1 != arg_count) { 295245651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes return JDWP::ERR_ILLEGAL_ARGUMENT; 295345651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } 295445651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes const char* shorty = mh.GetShorty(); 29550920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes const DexFile::TypeList* types = mh.GetParameterTypeList(); 295645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes for (size_t i = 0; i < arg_count; ++i) { 295745651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes if (shorty[i + 1] != JdwpTagToShortyChar(arg_types[i])) { 295845651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes return JDWP::ERR_ILLEGAL_ARGUMENT; 295945651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } 29600920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes 29610920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes if (shorty[i + 1] == 'L') { 29620920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes // Did we really get an argument of an appropriate reference type? 29630920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes mirror::Class* parameter_type = mh.GetClassFromTypeIdx(types->GetTypeItem(i).type_idx_); 29640920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes mirror::Object* argument = gRegistry->Get<mirror::Object*>(arg_values[i]); 29650920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes if (argument == ObjectRegistry::kInvalidObject) { 29660920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 29670920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes } 29680630ab5239a7d7be24dedbc3f66c822332446fc3Sebastien Hertz if (argument != NULL && !argument->InstanceOf(parameter_type)) { 29690920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes return JDWP::ERR_ILLEGAL_ARGUMENT; 29700920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes } 29710920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes 29720920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes // Turn the on-the-wire ObjectId into a jobject. 29730920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes jvalue& v = reinterpret_cast<jvalue&>(arg_values[i]); 29740920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes v.l = gRegistry->GetJObject(arg_values[i]); 29750920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes } 297645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } 297745651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes 2978d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz req->receiver = receiver; 2979d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz req->thread = thread; 2980d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz req->klass = c; 2981d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz req->method = m; 2982d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz req->arg_count = arg_count; 2983d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz req->arg_values = arg_values; 2984d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz req->options = options; 2985d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz req->invoke_needed = true; 2986d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 2987d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 2988d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes // The fact that we've released the thread list lock is a bit risky --- if the thread goes 2989d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes // away we're sitting high and dry -- but we must release this before the ResumeAllThreads 2990d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes // call, and it's unwise to hold it during WaitForSuspend. 2991d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 2992d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes { 2993d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes /* 2994d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * We change our (JDWP thread) status, which should be THREAD_RUNNING, 299581ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes * so we can suspend for a GC if the invoke request causes us to 2996d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * run out of memory. It's also a good idea to change it before locking 2997d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * the invokeReq mutex, although that should never be held for long. 2998d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes */ 299900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers self->TransitionFromRunnableToSuspended(kWaitingForDebuggerSend); 3000d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 30014dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << " Transferring control to event thread"; 3002d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes { 3003d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz MutexLock mu(self, req->lock); 3004d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 3005d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes if ((options & JDWP::INVOKE_SINGLE_THREADED) == 0) { 30064dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << " Resuming all threads"; 300700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers thread_list->UndoDebuggerSuspensions(); 3008d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } else { 30094dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << " Resuming event thread only"; 3010d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes thread_list->Resume(targetThread, true); 3011d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 3012d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 3013d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes // Wait for the request to finish executing. 3014d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz while (req->invoke_needed) { 3015d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz req->cond.Wait(self); 3016d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 3017d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 30184dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << " Control has returned from event thread"; 3019d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 3020d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes /* wait for thread to re-suspend itself */ 3021df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom SuspendThread(thread_id, false /* request_suspension */); 302200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers self->TransitionFromSuspendedToRunnable(); 3023d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 3024d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 3025d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes /* 3026d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * Suspend the threads. We waited for the target thread to suspend 3027d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * itself, so all we need to do is suspend the others. 3028d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * 3029d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * The suspendAllThreads() call will double-suspend the event thread, 3030d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * so we want to resume the target thread once to keep the books straight. 3031d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes */ 3032d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes if ((options & JDWP::INVOKE_SINGLE_THREADED) == 0) { 303300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers self->TransitionFromRunnableToSuspended(kWaitingForDebuggerSuspension); 30344dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << " Suspending all threads"; 303500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers thread_list->SuspendAllForDebugger(); 303600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers self->TransitionFromSuspendedToRunnable(); 30374dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << " Resuming event thread to balance the count"; 3038d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes thread_list->Resume(targetThread, true); 3039d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 3040d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 3041d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes // Copy the result. 3042d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes *pResultTag = req->result_tag; 3043d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes if (IsPrimitiveTag(req->result_tag)) { 3044f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes *pResultValue = req->result_value.GetJ(); 3045d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } else { 3046f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes *pResultValue = gRegistry->Add(req->result_value.GetL()); 3047d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 3048d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes *pExceptionId = req->exception; 3049d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes return req->error; 3050872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 3051872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 3052872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::ExecuteMethod(DebugInvokeReq* pReq) { 305300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 3054d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 305581ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes // We can be called while an exception is pending. We need 3056d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes // to preserve that across the method invocation. 305762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers SirtRef<mirror::Object> old_throw_this_object(soa.Self(), NULL); 3058ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom SirtRef<mirror::ArtMethod> old_throw_method(soa.Self(), NULL); 305962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers SirtRef<mirror::Throwable> old_exception(soa.Self(), NULL); 306062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers uint32_t old_throw_dex_pc; 306162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers { 306262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowLocation old_throw_location; 306362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers mirror::Throwable* old_exception_obj = soa.Self()->GetException(&old_throw_location); 306462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers old_throw_this_object.reset(old_throw_location.GetThis()); 306562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers old_throw_method.reset(old_throw_location.GetMethod()); 306662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers old_exception.reset(old_exception_obj); 306762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers old_throw_dex_pc = old_throw_location.GetDexPc(); 306862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers soa.Self()->ClearException(); 306962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 3070d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 3071d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes // Translate the method through the vtable, unless the debugger wants to suppress it. 3072c528dba35b5faece51ca658fc008b688f8b690adMathieu Chartier SirtRef<mirror::ArtMethod> m(soa.Self(), pReq->method); 3073d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz if ((pReq->options & JDWP::INVOKE_NONVIRTUAL) == 0 && pReq->receiver != NULL) { 3074d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz mirror::ArtMethod* actual_method = pReq->klass->FindVirtualMethodForVirtualOrInterface(pReq->method); 3075c528dba35b5faece51ca658fc008b688f8b690adMathieu Chartier if (actual_method != m.get()) { 3076c528dba35b5faece51ca658fc008b688f8b690adMathieu Chartier VLOG(jdwp) << "ExecuteMethod translated " << PrettyMethod(m.get()) << " to " << PrettyMethod(actual_method); 3077c528dba35b5faece51ca658fc008b688f8b690adMathieu Chartier m.reset(actual_method); 307845651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } 3079d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 3080c528dba35b5faece51ca658fc008b688f8b690adMathieu Chartier VLOG(jdwp) << "ExecuteMethod " << PrettyMethod(m.get()) 3081d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz << " receiver=" << pReq->receiver 3082d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz << " arg_count=" << pReq->arg_count; 3083c528dba35b5faece51ca658fc008b688f8b690adMathieu Chartier CHECK(m.get() != nullptr); 3084d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 3085d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes CHECK_EQ(sizeof(jvalue), sizeof(uint64_t)); 3086d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 308753b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers pReq->result_value = InvokeWithJValues(soa, pReq->receiver, soa.EncodeMethod(pReq->method), 308853b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers reinterpret_cast<jvalue*>(pReq->arg_values)); 3089d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 309062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers mirror::Throwable* exception = soa.Self()->GetException(NULL); 309162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers soa.Self()->ClearException(); 309262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers pReq->exception = gRegistry->Add(exception); 3093c528dba35b5faece51ca658fc008b688f8b690adMathieu Chartier pReq->result_tag = BasicTagFromDescriptor(MethodHelper(m.get()).GetShorty()); 3094d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes if (pReq->exception != 0) { 309562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers VLOG(jdwp) << " JDWP invocation returning with exception=" << exception 309662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers << " " << exception->Dump(); 3097f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes pReq->result_value.SetJ(0); 3098d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } else if (pReq->result_tag == JDWP::JT_OBJECT) { 3099d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes /* if no exception thrown, examine object result more closely */ 31009837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers JDWP::JdwpTag new_tag = TagFromObject(soa, pReq->result_value.GetL()); 3101d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes if (new_tag != pReq->result_tag) { 31024dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << " JDWP promoted result from " << pReq->result_tag << " to " << new_tag; 3103d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes pReq->result_tag = new_tag; 3104d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 3105d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 3106d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes /* 3107d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * Register the object. We don't actually need an ObjectId yet, 3108d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * but we do need to be sure that the GC won't move or discard the 3109d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * object when we switch out of RUNNING. The ObjectId conversion 3110d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * will add the object to the "do not touch" list. 3111d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * 3112d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * We can't use the "tracked allocation" mechanism here because 3113d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * the object is going to be handed off to a different thread. 3114d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes */ 3115f24d3cedd395690f6904aaac80f84a100420f7a3Elliott Hughes gRegistry->Add(pReq->result_value.GetL()); 3116d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 3117d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 3118d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes if (old_exception.get() != NULL) { 311962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowLocation gc_safe_throw_location(old_throw_this_object.get(), old_throw_method.get(), 312062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers old_throw_dex_pc); 312162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers soa.Self()->SetException(gc_safe_throw_location, old_exception.get()); 3122d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 3123872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 3124872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 3125d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes/* 31264b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes * "request" contains a full JDWP packet, possibly with multiple chunks. We 3127f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * need to process each, accumulate the replies, and ship the whole thing 3128f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * back. 3129f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * 3130f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * Returns "true" if we have a reply. The reply buffer is newly allocated, 3131f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * and includes the chunk type/length, followed by the data. 3132f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * 31333d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes * OLD-TODO: we currently assume that the request and reply include a single 3134f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * chunk. If this becomes inconvenient we will need to adapt. 3135f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes */ 31364b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughesbool Dbg::DdmHandlePacket(JDWP::Request& request, uint8_t** pReplyBuf, int* pReplyLen) { 3137f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes Thread* self = Thread::Current(); 3138f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes JNIEnv* env = self->GetJniEnv(); 3139f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 31404b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes uint32_t type = request.ReadUnsigned32("type"); 31414b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes uint32_t length = request.ReadUnsigned32("length"); 31424b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes 31434b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes // Create a byte[] corresponding to 'request'. 31444b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes size_t request_length = request.size(); 31454b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes ScopedLocalRef<jbyteArray> dataArray(env, env->NewByteArray(request_length)); 31466a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes if (dataArray.get() == NULL) { 31474b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes LOG(WARNING) << "byte[] allocation failed: " << request_length; 3148f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes env->ExceptionClear(); 3149f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes return false; 3150f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes } 31514b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes env->SetByteArrayRegion(dataArray.get(), 0, request_length, reinterpret_cast<const jbyte*>(request.data())); 31524b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes request.Skip(request_length); 3153f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 3154f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes // Run through and find all chunks. [Currently just find the first.] 31556a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes ScopedByteArrayRO contents(env, dataArray.get()); 31564b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes if (length != request_length) { 3157ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers LOG(WARNING) << StringPrintf("bad chunk found (len=%u pktLen=%zd)", length, request_length); 3158f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes return false; 3159f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes } 3160f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 3161f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes // Call "private static Chunk dispatch(int type, byte[] data, int offset, int length)". 3162eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes ScopedLocalRef<jobject> chunk(env, env->CallStaticObjectMethod(WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer, 3163eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer_dispatch, 31644b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes type, dataArray.get(), 0, length)); 3165f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes if (env->ExceptionCheck()) { 3166f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes LOG(INFO) << StringPrintf("Exception thrown by dispatcher for 0x%08x", type); 3167f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes env->ExceptionDescribe(); 3168f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes env->ExceptionClear(); 3169f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes return false; 3170f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes } 3171f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 31726a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes if (chunk.get() == NULL) { 3173f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes return false; 3174f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes } 3175f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 3176f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes /* 3177f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * Pull the pieces out of the chunk. We copy the results into a 3178f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * newly-allocated buffer that the caller can free. We don't want to 3179f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * continue using the Chunk object because nothing has a reference to it. 3180f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * 3181f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * We could avoid this by returning type/data/offset/length and having 3182f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * the caller be aware of the object lifetime issues, but that 318381ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes * integrates the JDWP code more tightly into the rest of the runtime, and doesn't work 3184f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * if we have responses for multiple chunks. 3185f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * 3186f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * So we're pretty much stuck with copying data around multiple times. 3187f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes */ 3188eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes ScopedLocalRef<jbyteArray> replyData(env, reinterpret_cast<jbyteArray>(env->GetObjectField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_data))); 31894b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes jint offset = env->GetIntField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_offset); 3190eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes length = env->GetIntField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_length); 3191eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes type = env->GetIntField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_type); 3192f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 31934dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << StringPrintf("DDM reply: type=0x%08x data=%p offset=%d length=%d", type, replyData.get(), offset, length); 31946a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes if (length == 0 || replyData.get() == NULL) { 3195f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes return false; 3196f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes } 3197f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 31984b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes const int kChunkHdrLen = 8; 3199f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes uint8_t* reply = new uint8_t[length + kChunkHdrLen]; 3200f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes if (reply == NULL) { 3201f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes LOG(WARNING) << "malloc failed: " << (length + kChunkHdrLen); 3202f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes return false; 3203f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes } 3204f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes JDWP::Set4BE(reply + 0, type); 3205f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes JDWP::Set4BE(reply + 4, length); 32066a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes env->GetByteArrayRegion(replyData.get(), offset, length, reinterpret_cast<jbyte*>(reply + kChunkHdrLen)); 3207f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 3208f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes *pReplyBuf = reply; 3209f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes *pReplyLen = length + kChunkHdrLen; 3210f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 32114b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes VLOG(jdwp) << StringPrintf("dvmHandleDdm returning type=%.4s %p len=%d", reinterpret_cast<char*>(reply), reply, length); 3212f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes return true; 3213872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 3214872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 3215a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughesvoid Dbg::DdmBroadcast(bool connect) { 32164dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << "Broadcasting DDM " << (connect ? "connect" : "disconnect") << "..."; 321747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 321847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes Thread* self = Thread::Current(); 321950b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers if (self->GetState() != kRunnable) { 322050b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers LOG(ERROR) << "DDM broadcast in thread state " << self->GetState(); 322150b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers /* try anyway? */ 322247fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes } 322347fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 322447fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes JNIEnv* env = self->GetJniEnv(); 322547fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes jint event = connect ? 1 /*DdmServer.CONNECTED*/ : 2 /*DdmServer.DISCONNECTED*/; 3226eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes env->CallStaticVoidMethod(WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer, 3227eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer_broadcast, 3228eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes event); 322947fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes if (env->ExceptionCheck()) { 323047fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes LOG(ERROR) << "DdmServer.broadcast " << event << " failed"; 323147fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes env->ExceptionDescribe(); 323247fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes env->ExceptionClear(); 323347fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes } 323447fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes} 323547fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 3236872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::DdmConnected() { 3237a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes Dbg::DdmBroadcast(true); 3238872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 3239872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 3240872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::DdmDisconnected() { 3241a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes Dbg::DdmBroadcast(false); 324247fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes gDdmThreadNotification = false; 324347fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes} 324447fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 324547fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes/* 32468218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes * Send a notification when a thread starts, stops, or changes its name. 324747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes * 324847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes * Because we broadcast the full set of threads when the notifications are 324947fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes * first enabled, it's possible for "thread" to be actively executing. 325047fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes */ 32518218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughesvoid Dbg::DdmSendThreadNotification(Thread* t, uint32_t type) { 325247fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes if (!gDdmThreadNotification) { 325347fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes return; 325447fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes } 325547fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 32568218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes if (type == CHUNK_TYPE("THDE")) { 32578218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes uint8_t buf[4]; 3258d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers JDWP::Set4BE(&buf[0], t->GetThreadId()); 32598218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes Dbg::DdmSendChunk(CHUNK_TYPE("THDE"), 4, buf); 32608218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes } else { 32618218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes CHECK(type == CHUNK_TYPE("THCR") || type == CHUNK_TYPE("THNM")) << type; 326200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 32632dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers SirtRef<mirror::String> name(soa.Self(), t->GetThreadName(soa)); 326447fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes size_t char_count = (name.get() != NULL) ? name->GetLength() : 0; 3265725a957985171d712d5c048cc3d00ff14968784bjeffhao const jchar* chars = (name.get() != NULL) ? name->GetCharArray()->GetData() : NULL; 326647fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 326721f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes std::vector<uint8_t> bytes; 3268d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers JDWP::Append4BE(bytes, t->GetThreadId()); 3269545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes JDWP::AppendUtf16BE(bytes, chars, char_count); 327021f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes CHECK_EQ(bytes.size(), char_count*2 + sizeof(uint32_t)*2); 327121f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes Dbg::DdmSendChunk(type, bytes); 327247fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes } 327347fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes} 327447fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 327547fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughesvoid Dbg::DdmSetThreadNotification(bool enable) { 327600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Enable/disable thread notifications. 327747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes gDdmThreadNotification = enable; 327847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes if (enable) { 327900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Suspend the VM then post thread start notifications for all threads. Threads attaching will 328000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // see a suspension in progress and block until that ends. They then post their own start 328100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // notification. 328200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers SuspendVM(); 328300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers std::list<Thread*> threads; 328450b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers Thread* self = Thread::Current(); 328500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers { 328650b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu(self, *Locks::thread_list_lock_); 328700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers threads = Runtime::Current()->GetThreadList()->GetList(); 328800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 328900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers { 329050b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers ScopedObjectAccess soa(self); 329102e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier for (Thread* thread : threads) { 329202e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier Dbg::DdmSendThreadNotification(thread, CHUNK_TYPE("THCR")); 329300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 329400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 329500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ResumeVM(); 329647fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes } 329747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes} 329847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 3299a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughesvoid Dbg::PostThreadStartOrStop(Thread* t, uint32_t type) { 3300c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes if (IsDebuggerActive()) { 3301dbe6f4613ae0161b169f4fca8a616b0b393370abMathieu Chartier ScopedObjectAccessUnchecked soa(Thread::Current()); 3302cfaa455374aae0a08c8cb28b5bb306b17866d652Ian Rogers JDWP::ObjectId id = gRegistry->Add(t->GetPeer()); 33038218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes gJdwpState->PostThreadChange(id, type == CHUNK_TYPE("THCR")); 330447fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes } 33058218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes Dbg::DdmSendThreadNotification(t, type); 330647fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes} 330747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 330847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughesvoid Dbg::PostThreadStart(Thread* t) { 3309a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes Dbg::PostThreadStartOrStop(t, CHUNK_TYPE("THCR")); 331047fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes} 331147fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 331247fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughesvoid Dbg::PostThreadDeath(Thread* t) { 3313a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes Dbg::PostThreadStartOrStop(t, CHUNK_TYPE("THDE")); 3314872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 3315872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 33168218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughesvoid Dbg::DdmSendChunk(uint32_t type, size_t byte_count, const uint8_t* buf) { 33173bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes CHECK(buf != NULL); 33183bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes iovec vec[1]; 33193bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes vec[0].iov_base = reinterpret_cast<void*>(const_cast<uint8_t*>(buf)); 33203bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes vec[0].iov_len = byte_count; 33213bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes Dbg::DdmSendChunkV(type, vec, 1); 3322872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 3323872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 332421f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughesvoid Dbg::DdmSendChunk(uint32_t type, const std::vector<uint8_t>& bytes) { 332521f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes DdmSendChunk(type, bytes.size(), &bytes[0]); 332621f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes} 332721f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes 3328f52935278fca8c7aa220543eef4544e3d1105d91Brian Carlstromvoid Dbg::DdmSendChunkV(uint32_t type, const iovec* iov, int iov_count) { 33293bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes if (gJdwpState == NULL) { 33304dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << "Debugger thread not active, ignoring DDM send: " << type; 33313bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } else { 3332cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes gJdwpState->DdmSendChunkV(type, iov, iov_count); 33333bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } 3334872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 3335872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 3336767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesint Dbg::DdmHandleHpifChunk(HpifWhen when) { 3337767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes if (when == HPIF_WHEN_NOW) { 33387162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes DdmSendHeapInfo(when); 3339767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes return true; 3340767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } 3341767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 3342767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes if (when != HPIF_WHEN_NEVER && when != HPIF_WHEN_NEXT_GC && when != HPIF_WHEN_EVERY_GC) { 3343767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes LOG(ERROR) << "invalid HpifWhen value: " << static_cast<int>(when); 3344767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes return false; 3345767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } 3346767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 3347767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes gDdmHpifWhen = when; 3348767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes return true; 3349767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes} 3350767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 3351767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesbool Dbg::DdmHandleHpsgNhsgChunk(Dbg::HpsgWhen when, Dbg::HpsgWhat what, bool native) { 3352767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes if (when != HPSG_WHEN_NEVER && when != HPSG_WHEN_EVERY_GC) { 3353767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes LOG(ERROR) << "invalid HpsgWhen value: " << static_cast<int>(when); 3354767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes return false; 3355767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } 3356767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 3357767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes if (what != HPSG_WHAT_MERGED_OBJECTS && what != HPSG_WHAT_DISTINCT_OBJECTS) { 3358767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes LOG(ERROR) << "invalid HpsgWhat value: " << static_cast<int>(what); 3359767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes return false; 3360767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } 3361767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 3362767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes if (native) { 3363767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes gDdmNhsgWhen = when; 3364767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes gDdmNhsgWhat = what; 3365767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } else { 3366767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes gDdmHpsgWhen = when; 3367767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes gDdmHpsgWhat = what; 3368767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } 3369767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes return true; 3370767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes} 3371767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 33727162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughesvoid Dbg::DdmSendHeapInfo(HpifWhen reason) { 33737162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes // If there's a one-shot 'when', reset it. 33747162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes if (reason == gDdmHpifWhen) { 33757162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes if (gDdmHpifWhen == HPIF_WHEN_NEXT_GC) { 33767162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes gDdmHpifWhen = HPIF_WHEN_NEVER; 33777162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes } 33787162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes } 33797162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes 33807162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes /* 33817162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * Chunk HPIF (client --> server) 33827162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * 33837162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * Heap Info. General information about the heap, 33847162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * suitable for a summary display. 33857162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * 33867162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * [u4]: number of heaps 33877162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * 33887162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * For each heap: 33897162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * [u4]: heap ID 33907162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * [u8]: timestamp in ms since Unix epoch 33917162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * [u1]: capture reason (same as 'when' value from server) 33927162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * [u4]: max heap size in bytes (-Xmx) 33937162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * [u4]: current heap size in bytes 33947162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * [u4]: current number of bytes allocated 33957162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * [u4]: current number of objects allocated 33967162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes */ 33977162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes uint8_t heap_count = 1; 33981d54e73444e017d3a65234e0f193846f3e27472bIan Rogers gc::Heap* heap = Runtime::Current()->GetHeap(); 339921f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes std::vector<uint8_t> bytes; 3400545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes JDWP::Append4BE(bytes, heap_count); 34017934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom JDWP::Append4BE(bytes, 1); // Heap id (bogus; we only have one heap). 3402545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes JDWP::Append8BE(bytes, MilliTime()); 3403545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes JDWP::Append1BE(bytes, reason); 34047934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom JDWP::Append4BE(bytes, heap->GetMaxMemory()); // Max allowed heap size in bytes. 34057934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom JDWP::Append4BE(bytes, heap->GetTotalMemory()); // Current heap size in bytes. 3406b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes JDWP::Append4BE(bytes, heap->GetBytesAllocated()); 3407b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes JDWP::Append4BE(bytes, heap->GetObjectsAllocated()); 340821f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes CHECK_EQ(bytes.size(), 4U + (heap_count * (4 + 8 + 1 + 4 + 4 + 4 + 4))); 340921f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes Dbg::DdmSendChunk(CHUNK_TYPE("HPIF"), bytes); 3410767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes} 3411767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 34126a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughesenum HpsgSolidity { 34136a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes SOLIDITY_FREE = 0, 34146a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes SOLIDITY_HARD = 1, 34156a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes SOLIDITY_SOFT = 2, 34166a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes SOLIDITY_WEAK = 3, 34176a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes SOLIDITY_PHANTOM = 4, 34186a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes SOLIDITY_FINALIZABLE = 5, 34196a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes SOLIDITY_SWEEP = 6, 34206a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes}; 34216a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 34226a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughesenum HpsgKind { 34236a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes KIND_OBJECT = 0, 34246a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes KIND_CLASS_OBJECT = 1, 34256a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes KIND_ARRAY_1 = 2, 34266a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes KIND_ARRAY_2 = 3, 34276a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes KIND_ARRAY_4 = 4, 34286a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes KIND_ARRAY_8 = 5, 34296a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes KIND_UNKNOWN = 6, 34306a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes KIND_NATIVE = 7, 34316a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes}; 34326a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 34336a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes#define HPSG_PARTIAL (1<<7) 34346a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes#define HPSG_STATE(solidity, kind) ((uint8_t)((((kind) & 0x7) << 3) | ((solidity) & 0x7))) 34356a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 343630fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogersclass HeapChunkContext { 343730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers public: 34386a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // Maximum chunk size. Obtain this from the formula: 34396a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // (((maximum_heap_size / ALLOCATION_UNIT_SIZE) + 255) / 256) * 2 34406a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes HeapChunkContext(bool merge, bool native) 344130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers : buf_(16384 - 16), 344230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers type_(0), 344330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers merge_(merge) { 34446a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes Reset(); 34456a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes if (native) { 344630fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers type_ = CHUNK_TYPE("NHSG"); 34476a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } else { 344830fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers type_ = merge ? CHUNK_TYPE("HPSG") : CHUNK_TYPE("HPSO"); 34496a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 34506a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 34516a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 34526a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes ~HeapChunkContext() { 345330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers if (p_ > &buf_[0]) { 34546a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes Flush(); 34556a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 34566a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 34576a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 34586a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes void EnsureHeader(const void* chunk_ptr) { 345930fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers if (!needHeader_) { 34606a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes return; 34616a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 34626a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 34636a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // Start a new HPSx chunk. 34647934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom JDWP::Write4BE(&p_, 1); // Heap id (bogus; we only have one heap). 34657934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom JDWP::Write1BE(&p_, 8); // Size of allocation unit, in bytes. 34666a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 34677934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom JDWP::Write4BE(&p_, reinterpret_cast<uintptr_t>(chunk_ptr)); // virtual address of segment start. 34687934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom JDWP::Write4BE(&p_, 0); // offset of this piece (relative to the virtual address). 34696a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // [u4]: length of piece, in allocation units 34706a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // We won't know this until we're done, so save the offset and stuff in a dummy value. 347130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers pieceLenField_ = p_; 347230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers JDWP::Write4BE(&p_, 0x55555555); 347330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers needHeader_ = false; 34746a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 34756a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 3476b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers void Flush() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 3477d636b0623307a379e255a9aaa682c12a2acc3a92Ian Rogers if (pieceLenField_ == NULL) { 3478d636b0623307a379e255a9aaa682c12a2acc3a92Ian Rogers // Flush immediately post Reset (maybe back-to-back Flush). Ignore. 3479d636b0623307a379e255a9aaa682c12a2acc3a92Ian Rogers CHECK(needHeader_); 3480d636b0623307a379e255a9aaa682c12a2acc3a92Ian Rogers return; 3481d636b0623307a379e255a9aaa682c12a2acc3a92Ian Rogers } 34826a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // Patch the "length of piece" field. 348330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers CHECK_LE(&buf_[0], pieceLenField_); 348430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers CHECK_LE(pieceLenField_, p_); 348530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers JDWP::Set4BE(pieceLenField_, totalAllocationUnits_); 34866a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 348730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers Dbg::DdmSendChunk(type_, p_ - &buf_[0], &buf_[0]); 34886a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes Reset(); 34896a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 34906a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 349100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers static void HeapChunkCallback(void* start, void* end, size_t used_bytes, void* arg) 3492b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, 3493b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers Locks::mutator_lock_) { 349430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers reinterpret_cast<HeapChunkContext*>(arg)->HeapChunkCallback(start, end, used_bytes); 3495a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 3496a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 34976a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes private: 3498a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes enum { ALLOCATION_UNIT_SIZE = 8 }; 3499a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 35006a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes void Reset() { 350130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers p_ = &buf_[0]; 350215bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers startOfNextMemoryChunk_ = NULL; 350330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers totalAllocationUnits_ = 0; 350430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers needHeader_ = true; 350530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers pieceLenField_ = NULL; 35066a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 35076a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 350800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void HeapChunkCallback(void* start, void* /*end*/, size_t used_bytes) 3509b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, 3510b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers Locks::mutator_lock_) { 351130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers // Note: heap call backs cannot manipulate the heap upon which they are crawling, care is taken 351230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers // in the following code not to allocate memory, by ensuring buf_ is of the correct size 351315bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers if (used_bytes == 0) { 351415bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers if (start == NULL) { 351515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers // Reset for start of new heap. 351615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers startOfNextMemoryChunk_ = NULL; 351715bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers Flush(); 351815bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers } 351915bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers // Only process in use memory so that free region information 352015bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers // also includes dlmalloc book keeping. 3521a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return; 3522a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 35236a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 352415bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers /* If we're looking at the native heap, we'll just return 352515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers * (SOLIDITY_HARD, KIND_NATIVE) for all allocated chunks 352615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers */ 352715bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers bool native = type_ == CHUNK_TYPE("NHSG"); 352815bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers 352915bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers if (startOfNextMemoryChunk_ != NULL) { 353015bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers // Transmit any pending free memory. Native free memory of 353115bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers // over kMaxFreeLen could be because of the use of mmaps, so 353215bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers // don't report. If not free memory then start a new segment. 353315bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers bool flush = true; 353415bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers if (start > startOfNextMemoryChunk_) { 353515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers const size_t kMaxFreeLen = 2 * kPageSize; 353615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers void* freeStart = startOfNextMemoryChunk_; 353715bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers void* freeEnd = start; 35382d88862f0752a7a0e65145b088f49dabd49d4284Brian Carlstrom size_t freeLen = reinterpret_cast<char*>(freeEnd) - reinterpret_cast<char*>(freeStart); 353915bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers if (!native || freeLen < kMaxFreeLen) { 354015bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers AppendChunk(HPSG_STATE(SOLIDITY_FREE, 0), freeStart, freeLen); 354115bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers flush = false; 354215bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers } 354315bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers } 354415bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers if (flush) { 354515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers startOfNextMemoryChunk_ = NULL; 354615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers Flush(); 354715bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers } 354815bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers } 3549ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::Object* obj = reinterpret_cast<mirror::Object*>(start); 3550a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 3551a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // Determine the type of this chunk. 3552a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // OLD-TODO: if context.merge, see if this chunk is different from the last chunk. 3553a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // If it's the same, we should combine them. 355415bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers uint8_t state = ExamineObject(obj, native); 355515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers // dlmalloc's chunk header is 2 * sizeof(size_t), but if the previous chunk is in use for an 355615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers // allocation then the first sizeof(size_t) may belong to it. 355715bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers const size_t dlMallocOverhead = sizeof(size_t); 355815bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers AppendChunk(state, start, used_bytes + dlMallocOverhead); 35592d88862f0752a7a0e65145b088f49dabd49d4284Brian Carlstrom startOfNextMemoryChunk_ = reinterpret_cast<char*>(start) + used_bytes + dlMallocOverhead; 356015bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers } 356115bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers 356215bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers void AppendChunk(uint8_t state, void* ptr, size_t length) 3563b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 356415bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers // Make sure there's enough room left in the buffer. 356515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers // We need to use two bytes for every fractional 256 allocation units used by the chunk plus 356615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers // 17 bytes for any header. 356715bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers size_t needed = (((length/ALLOCATION_UNIT_SIZE + 255) / 256) * 2) + 17; 356815bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers size_t bytesLeft = buf_.size() - (size_t)(p_ - &buf_[0]); 356915bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers if (bytesLeft < needed) { 357015bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers Flush(); 357115bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers } 3572a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 357315bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers bytesLeft = buf_.size() - (size_t)(p_ - &buf_[0]); 357415bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers if (bytesLeft < needed) { 357515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers LOG(WARNING) << "Chunk is too big to transmit (chunk_len=" << length << ", " 357615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers << needed << " bytes)"; 357715bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers return; 357815bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers } 357915bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers EnsureHeader(ptr); 3580a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // Write out the chunk description. 358115bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers length /= ALLOCATION_UNIT_SIZE; // Convert to allocation units. 358215bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers totalAllocationUnits_ += length; 358315bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers while (length > 256) { 358430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers *p_++ = state | HPSG_PARTIAL; 358530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers *p_++ = 255; // length - 1 358615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers length -= 256; 3587a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 358830fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers *p_++ = state; 358915bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers *p_++ = length - 1; 35906a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 35916a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 3592ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers uint8_t ExamineObject(mirror::Object* o, bool is_native_heap) 3593ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) { 3594a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes if (o == NULL) { 3595a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return HPSG_STATE(SOLIDITY_FREE, 0); 3596a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 35976a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 3598a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // It's an allocated chunk. Figure out what it is. 35996a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 3600a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // If we're looking at the native heap, we'll just return 3601a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // (SOLIDITY_HARD, KIND_NATIVE) for all allocated chunks. 360200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (is_native_heap) { 3603a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return HPSG_STATE(SOLIDITY_HARD, KIND_NATIVE); 36046a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 36056a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 36065bfa60ffcc953340feb711ed05cf576ac821905eIan Rogers if (!Runtime::Current()->GetHeap()->IsLiveObjectLocked(o)) { 360715bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers return HPSG_STATE(SOLIDITY_HARD, KIND_NATIVE); 360800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 360900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 36102dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = o->GetClass(); 3611a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes if (c == NULL) { 3612a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // The object was probably just created but hasn't been initialized yet. 3613a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT); 3614a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 36156a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 3616590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) { 361715bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers LOG(ERROR) << "Invalid class for managed heap object: " << o << " " << c; 3618a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return HPSG_STATE(SOLIDITY_HARD, KIND_UNKNOWN); 3619a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 36206a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 3621a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes if (c->IsClassClass()) { 3622a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return HPSG_STATE(SOLIDITY_HARD, KIND_CLASS_OBJECT); 36236a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 36246a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 3625a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes if (c->IsArrayClass()) { 3626a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes if (o->IsObjectArray()) { 3627a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_4); 3628a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 3629a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes switch (c->GetComponentSize()) { 3630a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes case 1: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_1); 3631a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes case 2: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_2); 3632a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes case 4: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_4); 3633a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes case 8: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_8); 3634a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 36356a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 36366a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 3637a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT); 36386a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 36396a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 364030fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers std::vector<uint8_t> buf_; 364130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers uint8_t* p_; 364230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers uint8_t* pieceLenField_; 364315bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers void* startOfNextMemoryChunk_; 364430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers size_t totalAllocationUnits_; 364530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers uint32_t type_; 364630fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers bool merge_; 364730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers bool needHeader_; 364830fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers 3649a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes DISALLOW_COPY_AND_ASSIGN(HeapChunkContext); 3650a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes}; 36516a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 36526a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughesvoid Dbg::DdmSendHeapSegments(bool native) { 36536a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes Dbg::HpsgWhen when; 36546a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes Dbg::HpsgWhat what; 36556a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes if (!native) { 36566a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes when = gDdmHpsgWhen; 36576a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes what = gDdmHpsgWhat; 36586a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } else { 36596a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes when = gDdmNhsgWhen; 36606a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes what = gDdmNhsgWhat; 36616a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 36626a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes if (when == HPSG_WHEN_NEVER) { 36636a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes return; 36646a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 36656a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 36666a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // Figure out what kind of chunks we'll be sending. 36676a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes CHECK(what == HPSG_WHAT_MERGED_OBJECTS || what == HPSG_WHAT_DISTINCT_OBJECTS) << static_cast<int>(what); 36686a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 36696a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // First, send a heap start chunk. 36706a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes uint8_t heap_id[4]; 36717934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom JDWP::Set4BE(&heap_id[0], 1); // Heap id (bogus; we only have one heap). 36726a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes Dbg::DdmSendChunk(native ? CHUNK_TYPE("NHST") : CHUNK_TYPE("HPST"), sizeof(heap_id), heap_id); 36736a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 3674cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi Thread* self = Thread::Current(); 3675cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi 3676cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi // To allow the Walk/InspectAll() below to exclusively-lock the 3677cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi // mutator lock, temporarily release the shared access to the 3678cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi // mutator lock here by transitioning to the suspended state. 3679cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi Locks::mutator_lock_->AssertSharedHeld(self); 3680cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi self->TransitionFromRunnableToSuspended(kSuspended); 3681cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi 36826a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // Send a series of heap segment chunks. 3683a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes HeapChunkContext context((what == HPSG_WHAT_MERGED_OBJECTS), native); 3684a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes if (native) { 36851d54e73444e017d3a65234e0f193846f3e27472bIan Rogers dlmalloc_inspect_all(HeapChunkContext::HeapChunkCallback, &context); 3686a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } else { 36871d54e73444e017d3a65234e0f193846f3e27472bIan Rogers gc::Heap* heap = Runtime::Current()->GetHeap(); 36881d54e73444e017d3a65234e0f193846f3e27472bIan Rogers const std::vector<gc::space::ContinuousSpace*>& spaces = heap->GetContinuousSpaces(); 368962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_); 36901d54e73444e017d3a65234e0f193846f3e27472bIan Rogers typedef std::vector<gc::space::ContinuousSpace*>::const_iterator It; 36911d54e73444e017d3a65234e0f193846f3e27472bIan Rogers for (It cur = spaces.begin(), end = spaces.end(); cur != end; ++cur) { 3692cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi if ((*cur)->IsMallocSpace()) { 3693cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi (*cur)->AsMallocSpace()->Walk(HeapChunkContext::HeapChunkCallback, &context); 3694b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier } 3695b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier } 3696e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier // Walk the large objects, these are not in the AllocSpace. 3697e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier heap->GetLargeObjectsSpace()->Walk(HeapChunkContext::HeapChunkCallback, &context); 3698a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 36996a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 3700cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi // Shared-lock the mutator lock back. 3701cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi self->TransitionFromSuspendedToRunnable(); 3702cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi Locks::mutator_lock_->AssertSharedHeld(self); 3703cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi 37046a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // Finally, send a heap end chunk. 37056a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes Dbg::DdmSendChunk(native ? CHUNK_TYPE("NHEN") : CHUNK_TYPE("HPEN"), sizeof(heap_id), heap_id); 3706767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes} 3707767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 3708b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughesstatic size_t GetAllocTrackerMax() { 3709b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes#ifdef HAVE_ANDROID_OS 3710b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes // Check whether there's a system property overriding the number of records. 3711b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes const char* propertyName = "dalvik.vm.allocTrackerMax"; 3712b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes char allocRecordMaxString[PROPERTY_VALUE_MAX]; 3713b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes if (property_get(propertyName, allocRecordMaxString, "") > 0) { 3714b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes char* end; 3715b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes size_t value = strtoul(allocRecordMaxString, &end, 10); 3716b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes if (*end != '\0') { 37173e47a748eb646b8d2fc8e8c4f11b270d9ae2c607Ruben Brunk LOG(ERROR) << "Ignoring " << propertyName << " '" << allocRecordMaxString 37183e47a748eb646b8d2fc8e8c4f11b270d9ae2c607Ruben Brunk << "' --- invalid"; 3719b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes return kDefaultNumAllocRecords; 3720b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes } 3721b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes if (!IsPowerOfTwo(value)) { 37223e47a748eb646b8d2fc8e8c4f11b270d9ae2c607Ruben Brunk LOG(ERROR) << "Ignoring " << propertyName << " '" << allocRecordMaxString 37233e47a748eb646b8d2fc8e8c4f11b270d9ae2c607Ruben Brunk << "' --- not power of two"; 3724b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes return kDefaultNumAllocRecords; 3725b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes } 3726b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes return value; 3727b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes } 3728b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes#endif 3729b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes return kDefaultNumAllocRecords; 3730b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes} 3731b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes 3732545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughesvoid Dbg::SetAllocTrackingEnabled(bool enabled) { 3733719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers MutexLock mu(Thread::Current(), *alloc_tracker_lock_); 3734545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes if (enabled) { 3735545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes if (recent_allocation_records_ == NULL) { 3736719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers alloc_record_max_ = GetAllocTrackerMax(); 3737719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers LOG(INFO) << "Enabling alloc tracker (" << alloc_record_max_ << " entries of " 3738b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes << kMaxAllocRecordStackDepth << " frames, taking " 3739719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers << PrettySize(sizeof(AllocRecord) * alloc_record_max_) << ")"; 3740719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers alloc_record_head_ = alloc_record_count_ = 0; 3741719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers recent_allocation_records_ = new AllocRecord[alloc_record_max_]; 3742545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes CHECK(recent_allocation_records_ != NULL); 3743545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3744fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers Runtime::Current()->GetInstrumentation()->InstrumentQuickAllocEntryPoints(); 3745545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } else { 3746fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers Runtime::Current()->GetInstrumentation()->UninstrumentQuickAllocEntryPoints(); 3747545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes delete[] recent_allocation_records_; 3748545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes recent_allocation_records_ = NULL; 3749545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3750545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes} 3751545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 37520399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersstruct AllocRecordStackVisitor : public StackVisitor { 37537a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers AllocRecordStackVisitor(Thread* thread, AllocRecord* record) 3754b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 37557a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers : StackVisitor(thread, NULL), record(record), depth(0) {} 3756545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 375700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses 375800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // annotalysis. 375900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { 3760545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes if (depth >= kMaxAllocRecordStackDepth) { 3761530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return false; 3762545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3763ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* m = GetMethod(); 37640399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers if (!m->IsRuntimeMethod()) { 37650399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers record->stack[depth].method = m; 37660399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers record->stack[depth].dex_pc = GetDexPc(); 3767530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes ++depth; 3768545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3769530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return true; 3770545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3771545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3772545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes ~AllocRecordStackVisitor() { 3773545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes // Clear out any unused stack trace elements. 3774545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes for (; depth < kMaxAllocRecordStackDepth; ++depth) { 3775545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes record->stack[depth].method = NULL; 37760399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers record->stack[depth].dex_pc = 0; 3777545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3778545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3779545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3780545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes AllocRecord* record; 3781545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes size_t depth; 3782545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes}; 3783545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 37842dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersvoid Dbg::RecordAllocation(mirror::Class* type, size_t byte_count) { 3785545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes Thread* self = Thread::Current(); 3786545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes CHECK(self != NULL); 3787545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3788719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers MutexLock mu(self, *alloc_tracker_lock_); 3789545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes if (recent_allocation_records_ == NULL) { 3790545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes return; 3791545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3792545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3793545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes // Advance and clip. 3794719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers if (++alloc_record_head_ == alloc_record_max_) { 3795719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers alloc_record_head_ = 0; 3796545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3797545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3798545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes // Fill in the basics. 3799719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers AllocRecord* record = &recent_allocation_records_[alloc_record_head_]; 3800545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes record->type = type; 3801545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes record->byte_count = byte_count; 3802d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers record->thin_lock_id = self->GetThreadId(); 3803545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3804545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes // Fill in the stack trace. 38057a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers AllocRecordStackVisitor visitor(self, record); 38060399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers visitor.WalkStack(); 3807545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3808719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers if (alloc_record_count_ < alloc_record_max_) { 3809719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers ++alloc_record_count_; 3810545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3811545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes} 3812545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3813a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes// Returns the index of the head element. 3814a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes// 3815a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes// We point at the most-recently-written record, so if gAllocRecordCount is 1 3816a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes// we want to use the current element. Take "head+1" and subtract count 3817a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes// from it. 3818a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes// 3819a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes// We need to handle underflow in our circular buffer, so we add 3820b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes// gAllocRecordMax and then mask it back down. 3821719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogerssize_t Dbg::HeadIndex() { 3822719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers return (Dbg::alloc_record_head_ + 1 + Dbg::alloc_record_max_ - Dbg::alloc_record_count_) & 3823719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers (Dbg::alloc_record_max_ - 1); 3824545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes} 3825545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3826545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughesvoid Dbg::DumpRecentAllocations() { 382700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 3828719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers MutexLock mu(soa.Self(), *alloc_tracker_lock_); 3829545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes if (recent_allocation_records_ == NULL) { 3830545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes LOG(INFO) << "Not recording tracked allocations"; 3831545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes return; 3832545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3833545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3834545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes // "i" is the head of the list. We want to start at the end of the 3835545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes // list and move forward to the tail. 3836a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes size_t i = HeadIndex(); 3837719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers size_t count = alloc_record_count_; 3838545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3839719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers LOG(INFO) << "Tracked allocations, (head=" << alloc_record_head_ << " count=" << count << ")"; 3840545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes while (count--) { 3841545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes AllocRecord* record = &recent_allocation_records_[i]; 3842545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3843a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes LOG(INFO) << StringPrintf(" Thread %-2d %6zd bytes ", record->thin_lock_id, record->byte_count) 3844545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes << PrettyClass(record->type); 3845545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3846545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes for (size_t stack_frame = 0; stack_frame < kMaxAllocRecordStackDepth; ++stack_frame) { 3847ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::ArtMethod* m = record->stack[stack_frame].method; 3848545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes if (m == NULL) { 3849545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes break; 3850545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3851545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes LOG(INFO) << " " << PrettyMethod(m) << " line " << record->stack[stack_frame].LineNumber(); 3852545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3853545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3854545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes // pause periodically to help logcat catch up 3855545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes if ((count % 5) == 0) { 3856545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes usleep(40000); 3857545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3858545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3859719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers i = (i + 1) & (alloc_record_max_ - 1); 3860545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3861545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes} 3862545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 386383c8ee000d525017ead8753fce6bc1020249b96aMathieu Chartiervoid Dbg::UpdateObjectPointers(IsMarkedCallback* visitor, void* arg) { 3864719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers if (recent_allocation_records_ != nullptr) { 3865719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers MutexLock mu(Thread::Current(), *alloc_tracker_lock_); 3866719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers size_t i = HeadIndex(); 3867719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers size_t count = alloc_record_count_; 3868719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers while (count--) { 3869719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers AllocRecord* record = &recent_allocation_records_[i]; 3870719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers DCHECK(record != nullptr); 3871719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers record->UpdateObjectPointers(visitor, arg); 3872719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers i = (i + 1) & (alloc_record_max_ - 1); 3873412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier } 3874412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier } 3875412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier if (gRegistry != nullptr) { 3876412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier gRegistry->UpdateObjectPointers(visitor, arg); 3877412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier } 3878412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier} 3879412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier 3880412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartiervoid Dbg::AllowNewObjectRegistryObjects() { 3881412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier if (gRegistry != nullptr) { 3882412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier gRegistry->AllowNewObjects(); 3883412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier } 3884412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier} 3885412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier 3886412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartiervoid Dbg::DisallowNewObjectRegistryObjects() { 3887412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier if (gRegistry != nullptr) { 3888412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier gRegistry->DisallowNewObjects(); 3889412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier } 3890412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier} 3891412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier 3892545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughesclass StringTable { 3893545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes public: 3894545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes StringTable() { 3895545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3896545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 38976d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers void Add(const char* s) { 3898545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes table_.insert(s); 3899545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3900545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3901a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes size_t IndexOf(const char* s) const { 390202e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier auto it = table_.find(s); 3903a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes if (it == table_.end()) { 3904a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes LOG(FATAL) << "IndexOf(\"" << s << "\") failed"; 3905a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes } 3906a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes return std::distance(table_.begin(), it); 3907545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3908545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3909a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes size_t Size() const { 3910545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes return table_.size(); 3911545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3912545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3913a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes void WriteTo(std::vector<uint8_t>& bytes) const { 391402e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier for (const std::string& str : table_) { 391502e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier const char* s = str.c_str(); 39166d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers size_t s_len = CountModifiedUtf8Chars(s); 39176d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers UniquePtr<uint16_t> s_utf16(new uint16_t[s_len]); 39186d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers ConvertModifiedUtf8ToUtf16(s_utf16.get(), s); 39196d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers JDWP::AppendUtf16BE(bytes, s_utf16.get(), s_len); 3920545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3921545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3922545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3923545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes private: 3924a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes std::set<std::string> table_; 3925545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes DISALLOW_COPY_AND_ASSIGN(StringTable); 3926545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes}; 3927545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 3928545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes/* 3929545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * The data we send to DDMS contains everything we have recorded. 3930545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * 3931545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * Message header (all values big-endian): 3932545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (1b) message header len (to allow future expansion); includes itself 3933545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (1b) entry header len 3934545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (1b) stack frame len 3935545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) number of entries 3936545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (4b) offset to string table from start of message 3937545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) number of class name strings 3938545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) number of method name strings 3939545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) number of source file name strings 3940545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * For each entry: 3941545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (4b) total allocation size 3942221229cb523f849f165fdafbf9785010963715daElliott Hughes * (2b) thread id 3943545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) allocated object's class name index 3944545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (1b) stack depth 3945545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * For each stack frame: 3946545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) method's class name 3947545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) method name 3948545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) method source file 3949545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) line number, clipped to 32767; -2 if native; -1 if no source 3950545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (xb) class name strings 3951545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (xb) method name strings 3952545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (xb) source file strings 3953545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * 3954545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * As with other DDM traffic, strings are sent as a 4-byte length 3955545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * followed by UTF-16 data. 3956545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * 3957545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * We send up 16-bit unsigned indexes into string tables. In theory there 3958b1a5879d2c87a5af9f8dbd63a112b138b87135e4Elliott Hughes * can be (kMaxAllocRecordStackDepth * gAllocRecordMax) unique strings in 3959545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * each table, but in practice there should be far fewer. 3960545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * 3961545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * The chief reason for using a string table here is to keep the size of 3962545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * the DDMS message to a minimum. This is partly to make the protocol 3963545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * efficient, but also because we have to form the whole thing up all at 3964545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * once in a memory buffer. 3965545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * 3966545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * We use separate string tables for class names, method names, and source 3967545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * files to keep the indexes small. There will generally be no overlap 3968545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * between the contents of these tables. 3969545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes */ 3970545a064aca775ba801790fced3d713d8a87bfc61Elliott HughesjbyteArray Dbg::GetRecentAllocations() { 3971545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes if (false) { 3972545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes DumpRecentAllocations(); 3973545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 3974545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 397550b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers Thread* self = Thread::Current(); 397646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier std::vector<uint8_t> bytes; 397746e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier { 3978719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers MutexLock mu(self, *alloc_tracker_lock_); 397946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // 398046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // Part 1: generate string tables. 398146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // 398246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier StringTable class_names; 398346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier StringTable method_names; 398446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier StringTable filenames; 398546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier 3986719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers int count = alloc_record_count_; 398746e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier int idx = HeadIndex(); 398846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier while (count--) { 398946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier AllocRecord* record = &recent_allocation_records_[idx]; 399046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier 399146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier class_names.Add(ClassHelper(record->type).GetDescriptor()); 399246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier 399346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier MethodHelper mh; 399446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier for (size_t i = 0; i < kMaxAllocRecordStackDepth; i++) { 3995ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* m = record->stack[i].method; 399646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier if (m != NULL) { 399746e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier mh.ChangeMethod(m); 399846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier class_names.Add(mh.GetDeclaringClassDescriptor()); 399946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier method_names.Add(mh.GetName()); 400046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier filenames.Add(mh.GetDeclaringClassSourceFile()); 400146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier } 400246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier } 4003545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 4004719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers idx = (idx + 1) & (alloc_record_max_ - 1); 400546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier } 400646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier 4007719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers LOG(INFO) << "allocation records: " << alloc_record_count_; 400846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier 400946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // 401046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // Part 2: Generate the output and store it in the buffer. 401146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // 401246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier 401346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (1b) message header len (to allow future expansion); includes itself 401446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (1b) entry header len 401546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (1b) stack frame len 401646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier const int kMessageHeaderLen = 15; 401746e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier const int kEntryHeaderLen = 9; 401846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier const int kStackFrameLen = 8; 401946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append1BE(bytes, kMessageHeaderLen); 402046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append1BE(bytes, kEntryHeaderLen); 402146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append1BE(bytes, kStackFrameLen); 402246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier 402346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) number of entries 402446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (4b) offset to string table from start of message 402546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) number of class name strings 402646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) number of method name strings 402746e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) number of source file name strings 4028719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers JDWP::Append2BE(bytes, alloc_record_count_); 402946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier size_t string_table_offset = bytes.size(); 40307934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom JDWP::Append4BE(bytes, 0); // We'll patch this later... 403146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append2BE(bytes, class_names.Size()); 403246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append2BE(bytes, method_names.Size()); 403346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append2BE(bytes, filenames.Size()); 403446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier 4035719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers count = alloc_record_count_; 403646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier idx = HeadIndex(); 403746e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier while (count--) { 403846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // For each entry: 403946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (4b) total allocation size 404046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) thread id 404146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) allocated object's class name index 404246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (1b) stack depth 404346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier AllocRecord* record = &recent_allocation_records_[idx]; 404446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier size_t stack_depth = record->GetDepth(); 4045590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier ClassHelper kh(record->type); 404646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier size_t allocated_object_class_name_index = class_names.IndexOf(kh.GetDescriptor()); 404746e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append4BE(bytes, record->byte_count); 404846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append2BE(bytes, record->thin_lock_id); 404946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append2BE(bytes, allocated_object_class_name_index); 405046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append1BE(bytes, stack_depth); 405146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier 405246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier MethodHelper mh; 405346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier for (size_t stack_frame = 0; stack_frame < stack_depth; ++stack_frame) { 405446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // For each stack frame: 405546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) method's class name 405646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) method name 405746e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) method source file 405846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) line number, clipped to 32767; -2 if native; -1 if no source 405946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier mh.ChangeMethod(record->stack[stack_frame].method); 406046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier size_t class_name_index = class_names.IndexOf(mh.GetDeclaringClassDescriptor()); 406146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier size_t method_name_index = method_names.IndexOf(mh.GetName()); 406246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier size_t file_name_index = filenames.IndexOf(mh.GetDeclaringClassSourceFile()); 406346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append2BE(bytes, class_name_index); 406446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append2BE(bytes, method_name_index); 406546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append2BE(bytes, file_name_index); 406646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append2BE(bytes, record->stack[stack_frame].LineNumber()); 4067545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 406846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier 4069719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers idx = (idx + 1) & (alloc_record_max_ - 1); 4070545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 4071545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 407246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (xb) class name strings 407346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (xb) method name strings 407446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (xb) source file strings 407546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Set4BE(&bytes[string_table_offset], bytes.size()); 407646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier class_names.WriteTo(bytes); 407746e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier method_names.WriteTo(bytes); 407846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier filenames.WriteTo(bytes); 4079545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 408050b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers JNIEnv* env = self->GetJniEnv(); 4081545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes jbyteArray result = env->NewByteArray(bytes.size()); 4082545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes if (result != NULL) { 4083545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes env->SetByteArrayRegion(result, 0, bytes.size(), reinterpret_cast<const jbyte*>(&bytes[0])); 4084545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 4085545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes return result; 4086545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes} 4087545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 4088872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} // namespace art 4089