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 2346ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe#include "android-base/stringprintf.h" 2446ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe 25166db04e259ca51838c311891598664deeed85adIan Rogers#include "arch/context.h" 26c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier#include "art_field-inl.h" 27e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "art_method-inl.h" 28542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe#include "base/enums.h" 2980afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko#include "base/time_utils.h" 30545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes#include "class_linker.h" 312dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "class_linker-inl.h" 324f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h" 339323e6e44060545d6c4f925139572868f65b7fe3David Sehr#include "dex_file_annotations.h" 34776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers#include "dex_instruction.h" 356ea1a0e2168c8d9b6d97c075c73a72d84080f45bMingyao Yang#include "entrypoints/runtime_asm_entrypoints.h" 361d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/accounting/card_table-inl.h" 378c2ff641294715864013737fdec57cdfd410270cMan Cao#include "gc/allocation_record.h" 38aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier#include "gc/scoped_gc_critical_section.h" 391d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/large_object_space.h" 401d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/space-inl.h" 41eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier#include "handle_scope.h" 42cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz#include "jdwp/jdwp_priv.h" 4364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes#include "jdwp/object_registry.h" 4413b27842e88ccf1a42807c92daeb108e867dc4cdAndreas Gampe#include "jni_internal.h" 4528bd2e4f151267b34b8e1eb19c489d8d547bbf5cMathieu Chartier#include "jvalue-inl.h" 462dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class.h" 472dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h" 482dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class_loader.h" 492dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h" 502dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h" 51b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers#include "mirror/string-inl.h" 522dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/throwable.h" 533398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier#include "obj_ptr-inl.h" 5453b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers#include "reflection.h" 55a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes#include "safe_map.h" 560795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier#include "scoped_thread_state_change-inl.h" 576a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes#include "ScopedLocalRef.h" 58f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes#include "ScopedPrimitiveArray.h" 59eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier#include "handle_scope-inl.h" 60475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes#include "thread_list.h" 612dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "utf.h" 62eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "well_known_classes.h" 63475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes 64872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace art { 65872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 6646ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampeusing android::base::StringPrintf; 6746ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe 680462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertz// The key identifying the debugger to update instrumentation. 690462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertzstatic constexpr const char* kDbgInstrumentationKey = "Debugger"; 700462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertz 718c2ff641294715864013737fdec57cdfd410270cMan Cao// Limit alloc_record_count to the 2BE value (64k-1) that is the limit of the current protocol. 72306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstromstatic uint16_t CappedAllocRecordCount(size_t alloc_record_count) { 731ed11b9ad5512cf464cb1686640df53201fa5297Man Cao const size_t cap = 0xffff; 748c2ff641294715864013737fdec57cdfd410270cMan Cao if (alloc_record_count > cap) { 758c2ff641294715864013737fdec57cdfd410270cMan Cao return cap; 764345c46b8a927cf13d9bbe38f8cf0593f5de181bMathieu Chartier } 778c2ff641294715864013737fdec57cdfd410270cMan Cao return alloc_record_count; 784345c46b8a927cf13d9bbe38f8cf0593f5de181bMathieu Chartier} 794345c46b8a927cf13d9bbe38f8cf0593f5de181bMathieu Chartier 806c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light// Takes a method and returns a 'canonical' one if the method is default (and therefore potentially 816c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light// copied from some other class). This ensures that the debugger does not get confused as to which 826c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light// method we are in. 836c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Lightstatic ArtMethod* GetCanonicalMethod(ArtMethod* m) 84bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 856c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light if (LIKELY(!m->IsDefault())) { 866c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light return m; 876c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light } else { 886c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light mirror::Class* declaring_class = m->GetDeclaringClass(); 896c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light return declaring_class->FindDeclaredVirtualMethod(declaring_class->GetDexCache(), 906c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light m->GetDexMethodIndex(), 91542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe kRuntimePointerSize); 926c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light } 936c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light} 946c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light 9541af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartierclass Breakpoint : public ValueObject { 960ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi public: 9741af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier Breakpoint(ArtMethod* method, uint32_t dex_pc, DeoptimizationRequest::Kind deoptimization_kind) 986c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light : method_(GetCanonicalMethod(method)), 9941af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier dex_pc_(dex_pc), 10041af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier deoptimization_kind_(deoptimization_kind) { 101f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz CHECK(deoptimization_kind_ == DeoptimizationRequest::kNothing || 102f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz deoptimization_kind_ == DeoptimizationRequest::kSelectiveDeoptimization || 103f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz deoptimization_kind_ == DeoptimizationRequest::kFullDeoptimization); 1040ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi } 105a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz 106bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe Breakpoint(const Breakpoint& other) REQUIRES_SHARED(Locks::mutator_lock_) 10741af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier : method_(other.method_), 10841af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier dex_pc_(other.dex_pc_), 10941af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier deoptimization_kind_(other.deoptimization_kind_) {} 11041af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier 11141af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier // Method() is called from root visiting, do not use ScopedObjectAccess here or it can cause 11241af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier // GC to deadlock if another thread tries to call SuspendAll while the GC is in a runnable state. 11341af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier ArtMethod* Method() const { 11441af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier return method_; 1150ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi } 1163b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier 1170ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi uint32_t DexPc() const { 1180ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi return dex_pc_; 1190ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi } 1200ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi 121f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz DeoptimizationRequest::Kind GetDeoptimizationKind() const { 122f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz return deoptimization_kind_; 1233b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier } 1240ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi 1256c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light // Returns true if the method of this breakpoint and the passed in method should be considered the 1266c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light // same. That is, they are either the same method or they are copied from the same method. 127bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe bool IsInMethod(ArtMethod* m) const REQUIRES_SHARED(Locks::mutator_lock_) { 1286c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light return method_ == GetCanonicalMethod(m); 1296c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light } 1306c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light 1310ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi private: 1320ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi // The location of this breakpoint. 13341af5e50d0b5e9d13084a61cfe9dfa6b6e201a40Mathieu Chartier ArtMethod* method_; 1340ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi uint32_t dex_pc_; 1350ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi 1360ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi // Indicates whether breakpoint needs full deoptimization or selective deoptimization. 137f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz DeoptimizationRequest::Kind deoptimization_kind_; 1388696433d1b3d8ba15288483b777edd888de69135Elliott Hughes}; 1398696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 140ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertzstatic std::ostream& operator<<(std::ostream& os, const Breakpoint& rhs) 141bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 142709b070044354d9f47641f273edacaeeb0240ab7David Sehr os << StringPrintf("Breakpoint[%s @%#x]", ArtMethod::PrettyMethod(rhs.Method()).c_str(), 143709b070044354d9f47641f273edacaeeb0240ab7David Sehr rhs.DexPc()); 1448696433d1b3d8ba15288483b777edd888de69135Elliott Hughes return os; 1458696433d1b3d8ba15288483b777edd888de69135Elliott Hughes} 1468696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 1473f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertzclass DebugInstrumentationListener FINAL : public instrumentation::InstrumentationListener { 14862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers public: 14962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers DebugInstrumentationListener() {} 15062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers virtual ~DebugInstrumentationListener() {} 15162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 152e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier void MethodEntered(Thread* thread, mirror::Object* this_object, ArtMethod* method, 1539d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz uint32_t dex_pc) 154bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { 15562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (method->IsNative()) { 15662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // TODO: post location events is a suspension point and native method entry stubs aren't. 15762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return; 15862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 1599d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz if (IsListeningToDexPcMoved()) { 1609d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz // We also listen to kDexPcMoved instrumentation event so we know the DexPcMoved method is 1619d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz // going to be called right after us. To avoid sending JDWP events twice for this location, 1629d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz // we report the event in DexPcMoved. However, we must remind this is method entry so we 1639d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz // send the METHOD_ENTRY event. And we can also group it with other events for this location 1649d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz // like BREAKPOINT or SINGLE_STEP (or even METHOD_EXIT if this is a RETURN instruction). 1659d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz thread->SetDebugMethodEntry(); 1669d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz } else if (IsListeningToMethodExit() && IsReturn(method, dex_pc)) { 1679d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz // We also listen to kMethodExited instrumentation event and the current instruction is a 1689d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz // RETURN so we know the MethodExited method is going to be called right after us. To avoid 1699d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz // sending JDWP events twice for this location, we report the event(s) in MethodExited. 1709d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz // However, we must remind this is method entry so we send the METHOD_ENTRY event. And we can 1719d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz // also group it with other events for this location like BREAKPOINT or SINGLE_STEP. 1729d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz thread->SetDebugMethodEntry(); 1739d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz } else { 1749d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz Dbg::UpdateDebugger(thread, this_object, method, 0, Dbg::kMethodEntry, nullptr); 1759d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz } 17662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 17762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 178e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier void MethodExited(Thread* thread, mirror::Object* this_object, ArtMethod* method, 1793f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz uint32_t dex_pc, const JValue& return_value) 180bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { 18162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (method->IsNative()) { 18262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // TODO: post location events is a suspension point and native method entry stubs aren't. 18362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return; 18462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 1859d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz uint32_t events = Dbg::kMethodExit; 1869d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz if (thread->IsDebugMethodEntry()) { 1879d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz // It is also the method entry. 1889d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz DCHECK(IsReturn(method, dex_pc)); 1899d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz events |= Dbg::kMethodEntry; 1909d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz thread->ClearDebugMethodEntry(); 1919d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz } 1929d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz Dbg::UpdateDebugger(thread, this_object, method, dex_pc, events, &return_value); 19362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 19462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 1959d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz void MethodUnwind(Thread* thread ATTRIBUTE_UNUSED, mirror::Object* this_object ATTRIBUTE_UNUSED, 196e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* method, uint32_t dex_pc) 197bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { 19862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // We're not recorded to listen to this kind of event, so complain. 199709b070044354d9f47641f273edacaeeb0240ab7David Sehr LOG(ERROR) << "Unexpected method unwind event in debugger " << ArtMethod::PrettyMethod(method) 20051db44a194bafc3810a41164a8b39614f10e79dfSebastien Hertz << " " << dex_pc; 20162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 20262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 203e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier void DexPcMoved(Thread* thread, mirror::Object* this_object, ArtMethod* method, 2043f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz uint32_t new_dex_pc) 205bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { 2069d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz if (IsListeningToMethodExit() && IsReturn(method, new_dex_pc)) { 2079d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz // We also listen to kMethodExited instrumentation event and the current instruction is a 2089d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz // RETURN so we know the MethodExited method is going to be called right after us. Like in 2099d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz // MethodEntered, we delegate event reporting to MethodExited. 2109d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz // Besides, if this RETURN instruction is the only one in the method, we can send multiple 2119d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz // JDWP events in the same packet: METHOD_ENTRY, METHOD_EXIT, BREAKPOINT and/or SINGLE_STEP. 2129d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz // Therefore, we must not clear the debug method entry flag here. 2139d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz } else { 2149d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz uint32_t events = 0; 2159d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz if (thread->IsDebugMethodEntry()) { 2169d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz // It is also the method entry. 2179d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz events = Dbg::kMethodEntry; 2189d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz thread->ClearDebugMethodEntry(); 2199d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz } 2209d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz Dbg::UpdateDebugger(thread, this_object, method, new_dex_pc, events, nullptr); 2219d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz } 22262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 22362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 2249d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz void FieldRead(Thread* thread ATTRIBUTE_UNUSED, mirror::Object* this_object, 225e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* method, uint32_t dex_pc, ArtField* field) 226bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { 2273f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz Dbg::PostFieldAccessEvent(method, dex_pc, this_object, field); 22862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 2293f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz 2306a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers void FieldWritten(Thread* thread ATTRIBUTE_UNUSED, mirror::Object* this_object, 231e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* method, uint32_t dex_pc, ArtField* field, 2326a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers const JValue& field_value) 233bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { 2343f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz Dbg::PostFieldModificationEvent(method, dex_pc, this_object, field, &field_value); 2353f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz } 2363f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz 23714691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray void ExceptionCaught(Thread* thread ATTRIBUTE_UNUSED, mirror::Throwable* exception_object) 238bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { 23914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray Dbg::PostException(exception_object); 2403f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz } 2413f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz 24281f0f953c4bb159997046c962d44cb1898b1778dNicolas Geoffray // We only care about branches in the Jit. 24381f0f953c4bb159997046c962d44cb1898b1778dNicolas Geoffray void Branch(Thread* /*thread*/, ArtMethod* method, uint32_t dex_pc, int32_t dex_pc_offset) 244bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { 245709b070044354d9f47641f273edacaeeb0240ab7David Sehr LOG(ERROR) << "Unexpected branch event in debugger " << ArtMethod::PrettyMethod(method) 24681f0f953c4bb159997046c962d44cb1898b1778dNicolas Geoffray << " " << dex_pc << ", " << dex_pc_offset; 247e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 248e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 2495550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray // We only care about invokes in the Jit. 2505550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray void InvokeVirtualOrInterface(Thread* thread ATTRIBUTE_UNUSED, 2515550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray mirror::Object*, 2525550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray ArtMethod* method, 2535550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray uint32_t dex_pc, 2545550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray ArtMethod*) 255bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { 256709b070044354d9f47641f273edacaeeb0240ab7David Sehr LOG(ERROR) << "Unexpected invoke event in debugger " << ArtMethod::PrettyMethod(method) 2575550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray << " " << dex_pc; 2585550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray } 2595550ca8bcc742b109d77e62f3a0877c667d894d3Nicolas Geoffray 2603f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz private: 261e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier static bool IsReturn(ArtMethod* method, uint32_t dex_pc) 262bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 2639d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz const DexFile::CodeItem* code_item = method->GetCodeItem(); 2649d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz const Instruction* instruction = Instruction::At(&code_item->insns_[dex_pc]); 2659d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz return instruction->IsReturn(); 2669d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz } 2679d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz 268bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe static bool IsListeningToDexPcMoved() REQUIRES_SHARED(Locks::mutator_lock_) { 2699d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz return IsListeningTo(instrumentation::Instrumentation::kDexPcMoved); 2709d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz } 2719d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz 272bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe static bool IsListeningToMethodExit() REQUIRES_SHARED(Locks::mutator_lock_) { 2739d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz return IsListeningTo(instrumentation::Instrumentation::kMethodExited); 2749d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz } 2759d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz 2769d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz static bool IsListeningTo(instrumentation::Instrumentation::InstrumentationEvent event) 277bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 2789d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz return (Dbg::GetInstrumentationEvents() & event) != 0; 2799d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz } 2809d6bf69ad3012a9d843268fdd5325b6719b6d5f2Sebastien Hertz 2813f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz DISALLOW_COPY_AND_ASSIGN(DebugInstrumentationListener); 28262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} gDebugInstrumentationListener; 28362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 2844ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughes// JDWP is allowed unless the Zygote forbids it. 2854ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughesstatic bool gJdwpAllowed = true; 2864ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughes 287c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes// Was there a -Xrunjdwp or -agentlib:jdwp= argument on the command line? 2883bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughesstatic bool gJdwpConfigured = false; 2893bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes 290b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertz// JDWP options for debugging. Only valid if IsJdwpConfigured() is true. 291b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertzstatic JDWP::JdwpOptions gJdwpOptions; 292b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertz 2933bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes// Runtime JDWP state. 294c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic JDWP::JdwpState* gJdwpState = nullptr; 2953bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughesstatic bool gDebuggerConnected; // debugger or DDMS is connected. 2963bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes 29747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughesstatic bool gDdmThreadNotification = false; 29847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 299767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes// DDMS GC-related settings. 300767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesstatic Dbg::HpifWhen gDdmHpifWhen = Dbg::HPIF_WHEN_NEVER; 301767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesstatic Dbg::HpsgWhen gDdmHpsgWhen = Dbg::HPSG_WHEN_NEVER; 302767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesstatic Dbg::HpsgWhat gDdmHpsgWhat; 303767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesstatic Dbg::HpsgWhen gDdmNhsgWhen = Dbg::HPSG_WHEN_NEVER; 304767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesstatic Dbg::HpsgWhat gDdmNhsgWhat; 305767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 306eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyibool Dbg::gDebuggerActive = false; 3074e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertzbool Dbg::gDisposed = false; 3086995c60cd6657c10811055c42661a55b10b47cefSebastien HertzObjectRegistry* Dbg::gRegistry = nullptr; 309475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes 310138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz// Deoptimization support. 3114d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertzstd::vector<DeoptimizationRequest> Dbg::deoptimization_requests_; 3124d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertzsize_t Dbg::full_deoptimization_event_count_ = 0; 313138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 31442cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz// Instrumentation event reference counters. 31542cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertzsize_t Dbg::dex_pc_change_event_ref_count_ = 0; 31642cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertzsize_t Dbg::method_enter_event_ref_count_ = 0; 31742cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertzsize_t Dbg::method_exit_event_ref_count_ = 0; 31842cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertzsize_t Dbg::field_read_event_ref_count_ = 0; 31942cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertzsize_t Dbg::field_write_event_ref_count_ = 0; 32042cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertzsize_t Dbg::exception_catch_event_ref_count_ = 0; 32142cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertzuint32_t Dbg::instrumentation_events_ = 0; 32242cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz 32304bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas GampeDbg::DbgThreadLifecycleCallback Dbg::thread_lifecycle_callback_; 3240f01b583c3952d0219696480654a0db8fac4b661Andreas GampeDbg::DbgClassLoadCallback Dbg::class_load_callback_; 32504bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas Gampe 326138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz// Breakpoints. 32709bfc6a50bdc9366b13ac3ab479d9278c853d90ajeffhaostatic std::vector<Breakpoint> gBreakpoints GUARDED_BY(Locks::breakpoint_lock_); 3288696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 329bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartiervoid DebugInvokeReq::VisitRoots(RootVisitor* visitor, const RootInfo& root_info) { 330bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier receiver.VisitRootIfNonNull(visitor, root_info); // null for static method call. 331bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier klass.VisitRoot(visitor, root_info); 3323b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier} 3333b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier 334597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertzvoid SingleStepControl::AddDexPc(uint32_t dex_pc) { 335597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz dex_pcs_.insert(dex_pc); 336bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz} 337bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz 338597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertzbool SingleStepControl::ContainsDexPc(uint32_t dex_pc) const { 339597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz return dex_pcs_.find(dex_pc) == dex_pcs_.end(); 340bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz} 341bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz 3426c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Lightstatic bool IsBreakpoint(ArtMethod* m, uint32_t dex_pc) 34390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier REQUIRES(!Locks::breakpoint_lock_) 344bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 345ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz ReaderMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_); 346138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz for (size_t i = 0, e = gBreakpoints.size(); i < e; ++i) { 3476c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light if (gBreakpoints[i].DexPc() == dex_pc && gBreakpoints[i].IsInMethod(m)) { 3488696433d1b3d8ba15288483b777edd888de69135Elliott Hughes VLOG(jdwp) << "Hit breakpoint #" << i << ": " << gBreakpoints[i]; 3498696433d1b3d8ba15288483b777edd888de69135Elliott Hughes return true; 3508696433d1b3d8ba15288483b777edd888de69135Elliott Hughes } 3518696433d1b3d8ba15288483b777edd888de69135Elliott Hughes } 3528696433d1b3d8ba15288483b777edd888de69135Elliott Hughes return false; 3538696433d1b3d8ba15288483b777edd888de69135Elliott Hughes} 3548696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 35552d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertzstatic bool IsSuspendedForDebugger(ScopedObjectAccessUnchecked& soa, Thread* thread) 35690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier REQUIRES(!Locks::thread_suspend_count_lock_) { 3579e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes MutexLock mu(soa.Self(), *Locks::thread_suspend_count_lock_); 3589e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes // A thread may be suspended for GC; in this code, we really want to know whether 3599e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes // there's a debugger suspension active. 3609e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes return thread->IsSuspended() && thread->GetDebugSuspendCount() > 0; 3619e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes} 3629e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes 363c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic mirror::Array* DecodeNonNullArray(JDWP::RefTypeId id, JDWP::JdwpError* error) 364bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 3656995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz mirror::Object* o = Dbg::GetObjectRegistry()->Get<mirror::Object*>(id, error); 366c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (o == nullptr) { 367c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *error = JDWP::ERR_INVALID_OBJECT; 368c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return nullptr; 369436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes } 370436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes if (!o->IsArrayInstance()) { 371c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *error = JDWP::ERR_INVALID_ARRAY; 372c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return nullptr; 373436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes } 374c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *error = JDWP::ERR_NONE; 375436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return o->AsArray(); 376436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes} 377436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes 378c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic mirror::Class* DecodeClass(JDWP::RefTypeId id, JDWP::JdwpError* error) 379bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 3806995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz mirror::Object* o = Dbg::GetObjectRegistry()->Get<mirror::Object*>(id, error); 381c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (o == nullptr) { 382c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *error = JDWP::ERR_INVALID_OBJECT; 383c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return nullptr; 384436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes } 385436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes if (!o->IsClass()) { 386c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *error = JDWP::ERR_INVALID_CLASS; 387c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return nullptr; 388436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes } 389c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *error = JDWP::ERR_NONE; 390436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return o->AsClass(); 391436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes} 392436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes 393c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic Thread* DecodeThread(ScopedObjectAccessUnchecked& soa, JDWP::ObjectId thread_id, 394c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError* error) 395bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) 39690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_) { 3976995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz mirror::Object* thread_peer = Dbg::GetObjectRegistry()->Get<mirror::Object*>(thread_id, error); 398c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (thread_peer == nullptr) { 399221229cb523f849f165fdafbf9785010963715daElliott Hughes // This isn't even an object. 400c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *error = JDWP::ERR_INVALID_OBJECT; 401c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return nullptr; 402221229cb523f849f165fdafbf9785010963715daElliott Hughes } 403221229cb523f849f165fdafbf9785010963715daElliott Hughes 4040795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ObjPtr<mirror::Class> java_lang_Thread = 4050795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier soa.Decode<mirror::Class>(WellKnownClasses::java_lang_Thread); 406221229cb523f849f165fdafbf9785010963715daElliott Hughes if (!java_lang_Thread->IsAssignableFrom(thread_peer->GetClass())) { 407221229cb523f849f165fdafbf9785010963715daElliott Hughes // This isn't a thread. 408c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *error = JDWP::ERR_INVALID_THREAD; 409c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return nullptr; 410221229cb523f849f165fdafbf9785010963715daElliott Hughes } 411221229cb523f849f165fdafbf9785010963715daElliott Hughes 412692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 413c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers Thread* thread = Thread::FromManagedThread(soa, thread_peer); 414c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers // If thread is null then this a java.lang.Thread without a Thread*. Must be a un-started or a 415c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers // zombie. 416c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *error = (thread == nullptr) ? JDWP::ERR_THREAD_NOT_ALIVE : JDWP::ERR_NONE; 417c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return thread; 418436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes} 419436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes 42024437995cdac88b42e42b16d9aa121e833330999Elliott Hughesstatic JDWP::JdwpTag BasicTagFromDescriptor(const char* descriptor) { 42124437995cdac88b42e42b16d9aa121e833330999Elliott Hughes // JDWP deliberately uses the descriptor characters' ASCII values for its enum. 42224437995cdac88b42e42b16d9aa121e833330999Elliott Hughes // Note that by "basic" we mean that we don't get more specific than JT_OBJECT. 42324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes return static_cast<JDWP::JdwpTag>(descriptor[0]); 42424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes} 42524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes 4261ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogersstatic JDWP::JdwpTag BasicTagFromClass(mirror::Class* klass) 427bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 4281ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers std::string temp; 4291ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers const char* descriptor = klass->GetDescriptor(&temp); 4301ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers return BasicTagFromDescriptor(descriptor); 4311ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers} 4321ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers 4339837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogersstatic JDWP::JdwpTag TagFromClass(const ScopedObjectAccessUnchecked& soa, mirror::Class* c) 434bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 435c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers CHECK(c != nullptr); 43624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes if (c->IsArrayClass()) { 43724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes return JDWP::JT_ARRAY; 43824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } 43924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes if (c->IsStringClass()) { 44024437995cdac88b42e42b16d9aa121e833330999Elliott Hughes return JDWP::JT_STRING; 4419837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers } 4429837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers if (c->IsClassClass()) { 44324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes return JDWP::JT_CLASS_OBJECT; 44424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } 4459837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers { 4460795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ObjPtr<mirror::Class> thread_class = 4470795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier soa.Decode<mirror::Class>(WellKnownClasses::java_lang_Thread); 4489837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers if (thread_class->IsAssignableFrom(c)) { 4499837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers return JDWP::JT_THREAD; 4509837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers } 4519837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers } 4529837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers { 4530795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ObjPtr<mirror::Class> thread_group_class = 4540795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier soa.Decode<mirror::Class>(WellKnownClasses::java_lang_ThreadGroup); 4559837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers if (thread_group_class->IsAssignableFrom(c)) { 4569837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers return JDWP::JT_THREAD_GROUP; 4579837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers } 4589837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers } 4599837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers { 4600795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ObjPtr<mirror::Class> class_loader_class = 4610795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier soa.Decode<mirror::Class>(WellKnownClasses::java_lang_ClassLoader); 4629837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers if (class_loader_class->IsAssignableFrom(c)) { 4639837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers return JDWP::JT_CLASS_LOADER; 4649837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers } 4659837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers } 4669837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers return JDWP::JT_OBJECT; 46724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes} 46824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes 46924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes/* 47024437995cdac88b42e42b16d9aa121e833330999Elliott Hughes * Objects declared to hold Object might actually hold a more specific 47124437995cdac88b42e42b16d9aa121e833330999Elliott Hughes * type. The debugger may take a special interest in these (e.g. it 47224437995cdac88b42e42b16d9aa121e833330999Elliott Hughes * wants to display the contents of Strings), so we want to return an 47324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes * appropriate tag. 47424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes * 47524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes * Null objects are tagged JT_OBJECT. 47624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes */ 4776995c60cd6657c10811055c42661a55b10b47cefSebastien HertzJDWP::JdwpTag Dbg::TagFromObject(const ScopedObjectAccessUnchecked& soa, mirror::Object* o) { 478c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return (o == nullptr) ? JDWP::JT_OBJECT : TagFromClass(soa, o->GetClass()); 47924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes} 48024437995cdac88b42e42b16d9aa121e833330999Elliott Hughes 48124437995cdac88b42e42b16d9aa121e833330999Elliott Hughesstatic bool IsPrimitiveTag(JDWP::JdwpTag tag) { 48224437995cdac88b42e42b16d9aa121e833330999Elliott Hughes switch (tag) { 48324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes case JDWP::JT_BOOLEAN: 48424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes case JDWP::JT_BYTE: 48524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes case JDWP::JT_CHAR: 48624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes case JDWP::JT_FLOAT: 48724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes case JDWP::JT_DOUBLE: 48824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes case JDWP::JT_INT: 48924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes case JDWP::JT_LONG: 49024437995cdac88b42e42b16d9aa121e833330999Elliott Hughes case JDWP::JT_SHORT: 49124437995cdac88b42e42b16d9aa121e833330999Elliott Hughes case JDWP::JT_VOID: 49224437995cdac88b42e42b16d9aa121e833330999Elliott Hughes return true; 49324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes default: 49424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes return false; 49524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } 49624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes} 49724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes 498b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertzvoid Dbg::StartJdwp() { 499c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes if (!gJdwpAllowed || !IsJdwpConfigured()) { 500376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes // No JDWP for you! 501376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes return; 502376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes } 503376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes 504719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers CHECK(gRegistry == nullptr); 505475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes gRegistry = new ObjectRegistry; 506475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes 507d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes // Init JDWP if the debugger is enabled. This may connect out to a 508d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes // debugger, passively listen for a debugger, or block waiting for a 509d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes // debugger. 510b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertz gJdwpState = JDWP::JdwpState::Create(&gJdwpOptions); 511c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (gJdwpState == nullptr) { 512f8a2df7bbf1021058bc13d1f806a7fec3c89ee62Elliott Hughes // We probably failed because some other process has the port already, which means that 513f8a2df7bbf1021058bc13d1f806a7fec3c89ee62Elliott Hughes // if we don't abort the user is likely to think they're talking to us when they're actually 514f8a2df7bbf1021058bc13d1f806a7fec3c89ee62Elliott Hughes // talking to that other process. 5153d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes LOG(FATAL) << "Debugger thread failed to initialize"; 516d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes } 517d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes 518d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes // If a debugger has already attached, send the "welcome" message. 519d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes // This may cause us to suspend all threads. 520376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes if (gJdwpState->IsActive()) { 52100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 5227d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz gJdwpState->PostVMStart(); 523d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughes } 524872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 525872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 526d1cc8363d4f4bbac7568b1d02a5ca481cd10830fElliott Hughesvoid Dbg::StopJdwp() { 527c6345efb56f9096c4b1a1a90e1d8d847fc01d910Sebastien Hertz // Post VM_DEATH event before the JDWP connection is closed (either by the JDWP thread or the 528c6345efb56f9096c4b1a1a90e1d8d847fc01d910Sebastien Hertz // destruction of gJdwpState). 529c6345efb56f9096c4b1a1a90e1d8d847fc01d910Sebastien Hertz if (gJdwpState != nullptr && gJdwpState->IsActive()) { 530c6345efb56f9096c4b1a1a90e1d8d847fc01d910Sebastien Hertz gJdwpState->PostVMDeath(); 531c6345efb56f9096c4b1a1a90e1d8d847fc01d910Sebastien Hertz } 5320376e6b62bfb43b515b791f0a7afed2d0d8030bcSebastien Hertz // Prevent the JDWP thread from processing JDWP incoming packets after we close the connection. 5334e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz Dispose(); 534376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes delete gJdwpState; 535719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers gJdwpState = nullptr; 536475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes delete gRegistry; 537719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers gRegistry = nullptr; 538872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 539872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 540767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesvoid Dbg::GcDidFinish() { 541767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes if (gDdmHpifWhen != HPIF_WHEN_NEVER) { 54200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 5434d466a8e4587422c989705dce3b2a19e7f0137f5Brian Carlstrom VLOG(jdwp) << "Sending heap info to DDM"; 5447162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes DdmSendHeapInfo(gDdmHpifWhen); 545767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } 546767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes if (gDdmHpsgWhen != HPSG_WHEN_NEVER) { 54700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 5484d466a8e4587422c989705dce3b2a19e7f0137f5Brian Carlstrom VLOG(jdwp) << "Dumping heap to DDM"; 5496a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes DdmSendHeapSegments(false); 550767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } 551767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes if (gDdmNhsgWhen != HPSG_WHEN_NEVER) { 55200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 5534d466a8e4587422c989705dce3b2a19e7f0137f5Brian Carlstrom VLOG(jdwp) << "Dumping native heap to DDM"; 5546a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes DdmSendHeapSegments(true); 555767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } 556767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes} 557767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 5584ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughesvoid Dbg::SetJdwpAllowed(bool allowed) { 5594ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughes gJdwpAllowed = allowed; 5604ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughes} 5614ffd31315bc0d00ec278e85feed15985de5ac3dcElliott Hughes 562eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescubool Dbg::IsJdwpAllowed() { 563eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu return gJdwpAllowed; 564eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu} 565eb84221ffc00357be6d69e2e461c7a45ee96334aLeonard Mosescu 566872d4ec7225444d9400d30f9027247deb91012fdElliott HughesDebugInvokeReq* Dbg::GetInvokeReq() { 567475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes return Thread::Current()->GetInvokeReq(); 568475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes} 569475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes 570475fc23a4a7f35d1be87ea0b06c80df317a720acElliott HughesThread* Dbg::GetDebugThread() { 571c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return (gJdwpState != nullptr) ? gJdwpState->GetDebugThread() : nullptr; 572475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes} 573475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes 574475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughesvoid Dbg::ClearWaitForEventThread() { 5752bf93f48bbb417b358c9e3c77911ea6ec7307c15Sebastien Hertz gJdwpState->ReleaseJdwpTokenForEvent(); 576872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 577872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 578872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::Connected() { 5793bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes CHECK(!gDebuggerConnected); 5804dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << "JDWP has attached"; 5813bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes gDebuggerConnected = true; 5828696433d1b3d8ba15288483b777edd888de69135Elliott Hughes gDisposed = false; 5838696433d1b3d8ba15288483b777edd888de69135Elliott Hughes} 5848696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 585f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertzbool Dbg::RequiresDeoptimization() { 586f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz // We don't need deoptimization if everything runs with interpreter after 587f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz // enabling -Xint mode. 588f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz return !Runtime::Current()->GetInstrumentation()->IsForcedInterpretOnly(); 589f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz} 590f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz 591a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughesvoid Dbg::GoActive() { 592a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // Enable all debugging features, including scans for breakpoints. 593a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // This is a no-op if we're already active. 594a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // Only called from the JDWP handler thread. 595eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (IsDebuggerActive()) { 596a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return; 597a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 598a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 599aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier Thread* const self = Thread::Current(); 600c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes { 601c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes // TODO: dalvik only warned if there were breakpoints left over. clear in Dbg::Disconnected? 602aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier ReaderMutexLock mu(self, *Locks::breakpoint_lock_); 603c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes CHECK_EQ(gBreakpoints.size(), 0U); 604c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes } 605a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 606138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz { 607aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier MutexLock mu(self, *Locks::deoptimization_lock_); 6084d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz CHECK_EQ(deoptimization_requests_.size(), 0U); 6094d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz CHECK_EQ(full_deoptimization_event_count_, 0U); 61042cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz CHECK_EQ(dex_pc_change_event_ref_count_, 0U); 61142cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz CHECK_EQ(method_enter_event_ref_count_, 0U); 61242cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz CHECK_EQ(method_exit_event_ref_count_, 0U); 61342cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz CHECK_EQ(field_read_event_ref_count_, 0U); 61442cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz CHECK_EQ(field_write_event_ref_count_, 0U); 61542cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz CHECK_EQ(exception_catch_event_ref_count_, 0U); 616138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 617138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 61862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Runtime* runtime = Runtime::Current(); 619433b79a9130df5f2375b9d3d7518c1f3fb84a467Nicolas Geoffray // Best effort deoptimization if the runtime is non-Java debuggable. This happens when 620433b79a9130df5f2375b9d3d7518c1f3fb84a467Nicolas Geoffray // ro.debuggable is set, but the application is not debuggable, or when a standalone 621433b79a9130df5f2375b9d3d7518c1f3fb84a467Nicolas Geoffray // dalvikvm invocation is not passed the debuggable option (-Xcompiler-option --debuggable). 622433b79a9130df5f2375b9d3d7518c1f3fb84a467Nicolas Geoffray // 623433b79a9130df5f2375b9d3d7518c1f3fb84a467Nicolas Geoffray // The performance cost of this is non-negligible during native-debugging due to the 624f448016e70fa91269d3750384aab1ac98d7896fdDavid Srbecky // forced JIT, so we keep the AOT code in that case in exchange for limited native debugging. 625433b79a9130df5f2375b9d3d7518c1f3fb84a467Nicolas Geoffray if (!runtime->IsJavaDebuggable() && 626433b79a9130df5f2375b9d3d7518c1f3fb84a467Nicolas Geoffray !runtime->GetInstrumentation()->IsForcedInterpretOnly() && 627433b79a9130df5f2375b9d3d7518c1f3fb84a467Nicolas Geoffray !runtime->IsNativeDebuggable()) { 628433b79a9130df5f2375b9d3d7518c1f3fb84a467Nicolas Geoffray runtime->DeoptimizeBootImage(); 6296ea1a0e2168c8d9b6d97c075c73a72d84080f45bMingyao Yang } 6306ea1a0e2168c8d9b6d97c075c73a72d84080f45bMingyao Yang 6314f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier ScopedSuspendAll ssa(__FUNCTION__); 632f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz if (RequiresDeoptimization()) { 633f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz runtime->GetInstrumentation()->EnableDeoptimization(); 634f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz } 63542cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz instrumentation_events_ = 0; 636a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes gDebuggerActive = true; 63762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LOG(INFO) << "Debugger is active"; 638872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 639872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 640872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::Disconnected() { 641234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes CHECK(gDebuggerConnected); 642234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes 643c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes LOG(INFO) << "Debugger is no longer active"; 644234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes 64598810e34804e224e5ab302cd353393f72a45202bHiroshi Yamauchi // Suspend all threads and exclusively acquire the mutator lock. Remove the debugger as a listener 64662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // and clear the object registry. 64762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Runtime* runtime = Runtime::Current(); 64862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Thread* self = Thread::Current(); 6494f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier { 650aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier // Required for DisableDeoptimization. 651aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier gc::ScopedGCCriticalSection gcs(self, 652aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier gc::kGcCauseInstrumentation, 653aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier gc::kCollectorTypeInstrumentation); 6544f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier ScopedSuspendAll ssa(__FUNCTION__); 6554f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier // Debugger may not be active at this point. 6564f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier if (IsDebuggerActive()) { 6574f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier { 6584f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier // Since we're going to disable deoptimization, we clear the deoptimization requests queue. 6594f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier // This prevents us from having any pending deoptimization request when the debugger attaches 6604f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier // to us again while no event has been requested yet. 661a6b1ead81603513fd40b77fd72f06d8cb1f35276Mathieu Chartier MutexLock mu(self, *Locks::deoptimization_lock_); 6624f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier deoptimization_requests_.clear(); 6634f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier full_deoptimization_event_count_ = 0U; 6644f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier } 6654f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier if (instrumentation_events_ != 0) { 6664f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier runtime->GetInstrumentation()->RemoveListener(&gDebugInstrumentationListener, 6674f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier instrumentation_events_); 6684f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier instrumentation_events_ = 0; 6694f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier } 6704f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier if (RequiresDeoptimization()) { 6714f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier runtime->GetInstrumentation()->DisableDeoptimization(kDbgInstrumentationKey); 6724f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier } 6734f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier gDebuggerActive = false; 674f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz } 675aaea7343831b64f4351c9abc7493ec062adfaf53Sebastien Hertz } 67655f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz 67755f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz { 67855f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz ScopedObjectAccess soa(self); 67955f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz gRegistry->Clear(); 68055f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz } 68155f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz 68255f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz gDebuggerConnected = false; 683872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 684872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 685b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertzvoid Dbg::ConfigureJdwp(const JDWP::JdwpOptions& jdwp_options) { 686b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertz CHECK_NE(jdwp_options.transport, JDWP::kJdwpTransportUnknown); 687b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertz gJdwpOptions = jdwp_options; 688b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertz gJdwpConfigured = true; 689b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertz} 690b3b173bbbd1d1cbad555de13c3fa6765f5078bceSebastien Hertz 691c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughesbool Dbg::IsJdwpConfigured() { 6923bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes return gJdwpConfigured; 693872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 694872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 695872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesint64_t Dbg::LastDebuggerActivity() { 696ca9515205010099d006ac2fac244348a1e673dcbElliott Hughes return gJdwpState->LastDebuggerActivity(); 697872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 698872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 699872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::UndoDebuggerSuspensions() { 700234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes Runtime::Current()->GetThreadList()->UndoDebuggerSuspensions(); 701872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 702872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 70388d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughesstd::string Dbg::GetClassName(JDWP::RefTypeId class_id) { 704c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 705c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(class_id, &error); 706c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (o == nullptr) { 707c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (error == JDWP::ERR_NONE) { 7082cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier return "null"; 709c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers } else { 710c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return StringPrintf("invalid object %p", reinterpret_cast<void*>(class_id)); 711c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers } 7123d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes } 7133d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes if (!o->IsClass()) { 7147934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom return StringPrintf("non-class %p", o); // This is only used for debugging output anyway. 7153d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes } 7166995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz return GetClassName(o->AsClass()); 7176995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz} 7186995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz 7196995c60cd6657c10811055c42661a55b10b47cefSebastien Hertzstd::string Dbg::GetClassName(mirror::Class* klass) { 720a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz if (klass == nullptr) { 7212cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier return "null"; 722a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz } 7231ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers std::string temp; 7246995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz return DescriptorToName(klass->GetDescriptor(&temp)); 7253d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes} 7263d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes 727c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId* class_object_id) { 728436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes JDWP::JdwpError status; 729c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Class* c = DecodeClass(id, &status); 730c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (c == nullptr) { 731c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *class_object_id = 0; 732436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return status; 7332435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 734c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *class_object_id = gRegistry->Add(c); 735436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 7368696433d1b3d8ba15288483b777edd888de69135Elliott Hughes} 7378696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 738c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId* superclass_id) { 7393d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes JDWP::JdwpError status; 740c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Class* c = DecodeClass(id, &status); 741c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (c == nullptr) { 742c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *superclass_id = 0; 7433d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return status; 7443d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes } 7453d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes if (c->IsInterface()) { 7463d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes // http://code.google.com/p/android/issues/detail?id=20856 747c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *superclass_id = 0; 7483d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes } else { 749c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *superclass_id = gRegistry->Add(c->GetSuperClass()); 7503d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes } 7513d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return JDWP::ERR_NONE; 752872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 753872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 754436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott HughesJDWP::JdwpError Dbg::GetClassLoader(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) { 755c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 7567929a489a9b256020d3add793198ba1e97e426e6Andreas Gampe mirror::Class* c = DecodeClass(id, &error); 7577929a489a9b256020d3add793198ba1e97e426e6Andreas Gampe if (c == nullptr) { 7587929a489a9b256020d3add793198ba1e97e426e6Andreas Gampe return error; 759436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes } 7607929a489a9b256020d3add793198ba1e97e426e6Andreas Gampe expandBufAddObjectId(pReply, gRegistry->Add(c->GetClassLoader())); 761436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 762872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 763872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 764436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott HughesJDWP::JdwpError Dbg::GetModifiers(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) { 765c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 766c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Class* c = DecodeClass(id, &error); 767c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (c == nullptr) { 768c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 7697b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 770436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes 771436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes uint32_t access_flags = c->GetAccessFlags() & kAccJavaFlagsMask; 772436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes 773de34eea060edb4eb34d6ecd840e6e1c4c6489642Yevgeny Rouban // Set ACC_SUPER. Dex files don't contain this flag but only classes are supposed to have it set, 774de34eea060edb4eb34d6ecd840e6e1c4c6489642Yevgeny Rouban // not interfaces. 775436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes // Class.getModifiers doesn't return it, but JDWP does, so we set it here. 776de34eea060edb4eb34d6ecd840e6e1c4c6489642Yevgeny Rouban if ((access_flags & kAccInterface) == 0) { 777de34eea060edb4eb34d6ecd840e6e1c4c6489642Yevgeny Rouban access_flags |= kAccSuper; 778de34eea060edb4eb34d6ecd840e6e1c4c6489642Yevgeny Rouban } 779436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes 780436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes expandBufAdd4BE(pReply, access_flags); 781436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes 782436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 783872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 784872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 785c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetMonitorInfo(JDWP::ObjectId object_id, JDWP::ExpandBuf* reply) { 786c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 787c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error); 788c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (o == nullptr) { 789f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 790f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes } 791f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes 792f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes // Ensure all threads are suspended while we read objects' lock words. 793f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes Thread* self = Thread::Current(); 7945426324ea7a4c334cde1fdc4b8aae39f8a8e362dSebastien Hertz CHECK_EQ(self->GetState(), kRunnable); 795f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes 796f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier MonitorInfo monitor_info; 797f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier { 798f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier ScopedThreadSuspension sts(self, kSuspended); 7994f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier ScopedSuspendAll ssa(__FUNCTION__); 800f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier monitor_info = MonitorInfo(o); 801f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier } 802c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (monitor_info.owner_ != nullptr) { 803cafa08146648442ee53348c4918a4fab29e591c1Nicolas Geoffray expandBufAddObjectId(reply, gRegistry->Add(monitor_info.owner_->GetPeerFromOtherThread())); 804f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes } else { 805c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers expandBufAddObjectId(reply, gRegistry->Add(nullptr)); 806f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes } 807d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers expandBufAdd4BE(reply, monitor_info.entry_count_); 808d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers expandBufAdd4BE(reply, monitor_info.waiters_.size()); 809d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers for (size_t i = 0; i < monitor_info.waiters_.size(); ++i) { 810cafa08146648442ee53348c4918a4fab29e591c1Nicolas Geoffray expandBufAddObjectId(reply, gRegistry->Add(monitor_info.waiters_[i]->GetPeerFromOtherThread())); 811f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes } 812f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes return JDWP::ERR_NONE; 813f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes} 814f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes 815734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott HughesJDWP::JdwpError Dbg::GetOwnedMonitors(JDWP::ObjectId thread_id, 816c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers std::vector<JDWP::ObjectId>* monitors, 817c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers std::vector<uint32_t>* stack_depths) { 8184993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes struct OwnedMonitorVisitor : public StackVisitor { 819b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi OwnedMonitorVisitor(Thread* thread, Context* context, 820cc8c5c5433230818cfe31617308198f286cc2ee1Hiroshi Yamauchi std::vector<JDWP::ObjectId>* monitor_vector, 821b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi std::vector<uint32_t>* stack_depth_vector) 822bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) 8238e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames), 8248e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray current_stack_depth(0), 8258e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray monitors(monitor_vector), 8268e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray stack_depths(stack_depth_vector) {} 8274993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes 8284993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses 8294993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes // annotalysis. 8304993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { 8314993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes if (!GetMethod()->IsRuntimeMethod()) { 8324993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes Monitor::VisitLocks(this, AppendOwnedMonitors, this); 833734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes ++current_stack_depth; 8344993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes } 8354993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes return true; 8364993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes } 8374993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes 838cc8c5c5433230818cfe31617308198f286cc2ee1Hiroshi Yamauchi static void AppendOwnedMonitors(mirror::Object* owned_monitor, void* arg) 839bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 8407a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers OwnedMonitorVisitor* visitor = reinterpret_cast<OwnedMonitorVisitor*>(arg); 841cc8c5c5433230818cfe31617308198f286cc2ee1Hiroshi Yamauchi visitor->monitors->push_back(gRegistry->Add(owned_monitor)); 842b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi visitor->stack_depths->push_back(visitor->current_stack_depth); 8434993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes } 8444993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes 845734b8c62cc637c25f4c2481ca6a48adbd7209c6cElliott Hughes size_t current_stack_depth; 846c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers std::vector<JDWP::ObjectId>* const monitors; 847c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers std::vector<uint32_t>* const stack_depths; 8484993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes }; 8494993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes 850b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi ScopedObjectAccessUnchecked soa(Thread::Current()); 851692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz JDWP::JdwpError error; 852692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz Thread* thread = DecodeThread(soa, thread_id, &error); 853692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz if (thread == nullptr) { 854692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz return error; 855692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz } 856692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz if (!IsSuspendedForDebugger(soa, thread)) { 857692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz return JDWP::ERR_THREAD_NOT_SUSPENDED; 8584993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes } 859cc8c5c5433230818cfe31617308198f286cc2ee1Hiroshi Yamauchi std::unique_ptr<Context> context(Context::Create()); 860c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers OwnedMonitorVisitor visitor(thread, context.get(), monitors, stack_depths); 861cc8c5c5433230818cfe31617308198f286cc2ee1Hiroshi Yamauchi visitor.WalkStack(); 8624993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes return JDWP::ERR_NONE; 8634993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes} 8644993bbc8eda377804e585efd918f8ab9d9eab7d4Elliott Hughes 86552d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien HertzJDWP::JdwpError Dbg::GetContendedMonitor(JDWP::ObjectId thread_id, 866c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::ObjectId* contended_monitor) { 867f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes ScopedObjectAccessUnchecked soa(Thread::Current()); 868c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *contended_monitor = 0; 869692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz JDWP::JdwpError error; 870692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz Thread* thread = DecodeThread(soa, thread_id, &error); 871692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz if (thread == nullptr) { 872692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz return error; 873692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz } 874692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz if (!IsSuspendedForDebugger(soa, thread)) { 875692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz return JDWP::ERR_THREAD_NOT_SUSPENDED; 876f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes } 877692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz mirror::Object* contended_monitor_obj = Monitor::GetContendedMonitor(thread); 878b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi // Add() requires the thread_list_lock_ not held to avoid the lock 879b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi // level violation. 880c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *contended_monitor = gRegistry->Add(contended_monitor_obj); 881f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes return JDWP::ERR_NONE; 882f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes} 883f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes 884ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott HughesJDWP::JdwpError Dbg::GetInstanceCounts(const std::vector<JDWP::RefTypeId>& class_ids, 885c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers std::vector<uint64_t>* counts) { 886412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier gc::Heap* heap = Runtime::Current()->GetHeap(); 887412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier heap->CollectGarbage(false); 888e8a3c576301fd531d5f73a65fc8b84a63619d580Mathieu Chartier VariableSizedHandleScope hs(Thread::Current()); 8899d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier std::vector<Handle<mirror::Class>> classes; 890c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers counts->clear(); 891ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes for (size_t i = 0; i < class_ids.size(); ++i) { 892c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 8939d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier ObjPtr<mirror::Class> c = DecodeClass(class_ids[i], &error); 894c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (c == nullptr) { 895c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 896ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes } 8979d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier classes.push_back(hs.NewHandle(c)); 898c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers counts->push_back(0); 899ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes } 900c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers heap->CountInstances(classes, false, &(*counts)[0]); 901ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes return JDWP::ERR_NONE; 902ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes} 903ec0f83d95e2174c97e93279ffa71642be7e12b60Elliott Hughes 904c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetInstances(JDWP::RefTypeId class_id, int32_t max_count, 905c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers std::vector<JDWP::ObjectId>* instances) { 906412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier gc::Heap* heap = Runtime::Current()->GetHeap(); 907412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier // We only want reachable instances, so do a GC. 908412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier heap->CollectGarbage(false); 909c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 9109d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier ObjPtr<mirror::Class> c = DecodeClass(class_id, &error); 911412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier if (c == nullptr) { 912c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 9133b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes } 9142d8559517759dcfac749a28d6713d36809ec556fMathieu Chartier VariableSizedHandleScope hs(Thread::Current()); 9152d8559517759dcfac749a28d6713d36809ec556fMathieu Chartier std::vector<Handle<mirror::Object>> raw_instances; 9162d8559517759dcfac749a28d6713d36809ec556fMathieu Chartier Runtime::Current()->GetHeap()->GetInstances(hs, hs.NewHandle(c), max_count, raw_instances); 9173b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes for (size_t i = 0; i < raw_instances.size(); ++i) { 9182d8559517759dcfac749a28d6713d36809ec556fMathieu Chartier instances->push_back(gRegistry->Add(raw_instances[i].Get())); 9193b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes } 9203b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes return JDWP::ERR_NONE; 9213b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes} 9223b78c949ab839d21454bc6f18c7640d2ae8c22f3Elliott Hughes 9230cbaff584244ee767027aff35cd3c625aaee2994Elliott HughesJDWP::JdwpError Dbg::GetReferringObjects(JDWP::ObjectId object_id, int32_t max_count, 924c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers std::vector<JDWP::ObjectId>* referring_objects) { 925412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier gc::Heap* heap = Runtime::Current()->GetHeap(); 926412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier heap->CollectGarbage(false); 927c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 9289d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier ObjPtr<mirror::Object> o = gRegistry->Get<mirror::Object*>(object_id, &error); 929c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (o == nullptr) { 9300cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 9310cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes } 932aea9bfb051bb197fdfb63d56ff0f3d63b36eb499Mathieu Chartier VariableSizedHandleScope hs(Thread::Current()); 933aea9bfb051bb197fdfb63d56ff0f3d63b36eb499Mathieu Chartier std::vector<Handle<mirror::Object>> raw_instances; 934aea9bfb051bb197fdfb63d56ff0f3d63b36eb499Mathieu Chartier heap->GetReferringObjects(hs, hs.NewHandle(o), max_count, raw_instances); 9350cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes for (size_t i = 0; i < raw_instances.size(); ++i) { 936aea9bfb051bb197fdfb63d56ff0f3d63b36eb499Mathieu Chartier referring_objects->push_back(gRegistry->Add(raw_instances[i].Get())); 9370cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes } 9380cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes return JDWP::ERR_NONE; 9390cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes} 9400cbaff584244ee767027aff35cd3c625aaee2994Elliott Hughes 941c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::DisableCollection(JDWP::ObjectId object_id) { 942c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 943c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error); 944c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (o == nullptr) { 945e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz return JDWP::ERR_INVALID_OBJECT; 946e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz } 94764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes gRegistry->DisableCollection(object_id); 94864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return JDWP::ERR_NONE; 94964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 95064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 951c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::EnableCollection(JDWP::ObjectId object_id) { 952c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 953c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error); 954e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz // Unlike DisableCollection, JDWP specs do not state an invalid object causes an error. The RI 955e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz // also ignores these cases and never return an error. However it's not obvious why this command 956e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz // should behave differently from DisableCollection and IsCollected commands. So let's be more 957e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz // strict and return an error if this happens. 958c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (o == nullptr) { 959e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz return JDWP::ERR_INVALID_OBJECT; 960e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz } 96164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes gRegistry->EnableCollection(object_id); 96264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return JDWP::ERR_NONE; 96364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 96464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 965c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::IsCollected(JDWP::ObjectId object_id, bool* is_collected) { 966c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *is_collected = true; 96765637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz if (object_id == 0) { 96865637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz // Null object id is invalid. 96965637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz return JDWP::ERR_INVALID_OBJECT; 97065637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz } 971e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz // JDWP specs state an INVALID_OBJECT error is returned if the object ID is not valid. However 97265637ebbb3c5bdf3f287a76df29a0340c10414c8Sebastien Hertz // the RI seems to ignore this and assume object has been collected. 973c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 974c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error); 975c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (o != nullptr) { 976c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *is_collected = gRegistry->IsCollected(object_id); 977e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz } 97864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return JDWP::ERR_NONE; 97964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 98064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 981c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersvoid Dbg::DisposeObject(JDWP::ObjectId object_id, uint32_t reference_count) { 98264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes gRegistry->DisposeObject(object_id, reference_count); 98364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 98464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 9853398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu ChartierJDWP::JdwpTypeTag Dbg::GetTypeTag(ObjPtr<mirror::Class> klass) { 9864d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz DCHECK(klass != nullptr); 9874d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz if (klass->IsArrayClass()) { 9884d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz return JDWP::TT_ARRAY; 9894d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz } else if (klass->IsInterface()) { 9904d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz return JDWP::TT_INTERFACE; 9914d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz } else { 9924d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz return JDWP::TT_CLASS; 9934d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz } 9944d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz} 9954d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz 99688d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::GetReflectedType(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) { 997c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 998c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Class* c = DecodeClass(class_id, &error); 999c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (c == nullptr) { 1000c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 10017b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 1002436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes 10034d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz JDWP::JdwpTypeTag type_tag = GetTypeTag(c); 10044d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz expandBufAdd1(pReply, type_tag); 100588d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes expandBufAddRefTypeId(pReply, class_id); 1006436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 1007872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1008872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1009e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier// Get the complete list of reference classes (i.e. all classes except 1010e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier// the primitive types). 1011e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier// Returns a newly-allocated buffer full of RefTypeId values. 1012e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartierclass ClassListCreator : public ClassVisitor { 1013e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier public: 1014e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier explicit ClassListCreator(std::vector<JDWP::RefTypeId>* classes) : classes_(classes) {} 10157b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes 101628357fab628bd9b91749988b554977398caf9963Mathieu Chartier bool operator()(ObjPtr<mirror::Class> c) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { 1017e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier if (!c->IsPrimitive()) { 1018e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier classes_->push_back(Dbg::GetObjectRegistry()->AddRefType(c)); 1019a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 1020e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier return true; 1021e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier } 1022a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 1023e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier private: 1024e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier std::vector<JDWP::RefTypeId>* const classes_; 1025e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier}; 1026a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 1027e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartiervoid Dbg::GetClassList(std::vector<JDWP::RefTypeId>* classes) { 10287b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes ClassListCreator clc(classes); 1029e0671ce5a6cb34e44e3afefa8e29c0c3e30d2855Mathieu Chartier Runtime::Current()->GetClassLinker()->VisitClassesWithoutClassesLock(&clc); 1030872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1031872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 10321ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian RogersJDWP::JdwpError Dbg::GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* pTypeTag, 10331ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers uint32_t* pStatus, std::string* pDescriptor) { 1034c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 1035c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Class* c = DecodeClass(class_id, &error); 1036c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (c == nullptr) { 1037c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 10387b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 10397b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes 1040a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes if (c->IsArrayClass()) { 1041a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes *pStatus = JDWP::CS_VERIFIED | JDWP::CS_PREPARED; 1042a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes *pTypeTag = JDWP::TT_ARRAY; 1043a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } else { 1044a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes if (c->IsErroneous()) { 1045a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes *pStatus = JDWP::CS_ERROR; 1046a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } else { 1047a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes *pStatus = JDWP::CS_VERIFIED | JDWP::CS_PREPARED | JDWP::CS_INITIALIZED; 1048a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 1049a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes *pTypeTag = c->IsInterface() ? JDWP::TT_INTERFACE : JDWP::TT_CLASS; 1050a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 1051a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 1052c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (pDescriptor != nullptr) { 10531ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers std::string temp; 10541ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers *pDescriptor = c->GetDescriptor(&temp); 1055a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 1056436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 1057872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1058872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1059c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersvoid Dbg::FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>* ids) { 106028357fab628bd9b91749988b554977398caf9963Mathieu Chartier std::vector<ObjPtr<mirror::Class>> classes; 1061b1d8c314b55bb2df2b2bb72a3daaf5db65b7ebc7Igor Murashkin Runtime::Current()->GetClassLinker()->LookupClasses(descriptor, classes); 1062c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers ids->clear(); 106328357fab628bd9b91749988b554977398caf9963Mathieu Chartier for (ObjPtr<mirror::Class> c : classes) { 106428357fab628bd9b91749988b554977398caf9963Mathieu Chartier ids->push_back(gRegistry->Add(c)); 10656fa602d614d418f38afebb4d44f42e7dc0b4bd94Elliott Hughes } 1066872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1067872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1068c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetReferenceType(JDWP::ObjectId object_id, JDWP::ExpandBuf* pReply) { 1069c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 1070c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error); 1071c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (o == nullptr) { 10722435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 10732435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 10742435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 10754d8fd49509fdcf203107fb33c62d8f451b6eb1d0Sebastien Hertz JDWP::JdwpTypeTag type_tag = GetTypeTag(o->GetClass()); 107664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes JDWP::RefTypeId type_id = gRegistry->AddRefType(o->GetClass()); 10772435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 10782435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes expandBufAdd1(pReply, type_tag); 10792435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes expandBufAddRefTypeId(pReply, type_id); 10802435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 10812435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes return JDWP::ERR_NONE; 1082872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1083872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1084fc0e94bed3f88ed7e50854fd8dfaf5dcb345250fIan RogersJDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId class_id, std::string* signature) { 1085c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 1086c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Class* c = DecodeClass(class_id, &error); 1087c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (c == nullptr) { 1088c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 10897b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 10901ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers std::string temp; 10911ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers *signature = c->GetDescriptor(&temp); 10921fe7afb88498d48d1f808ee31e986324f2a1c842Elliott Hughes return JDWP::ERR_NONE; 1093872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1094872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 109524d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion HodsonJDWP::JdwpError Dbg::GetSourceDebugExtension(JDWP::RefTypeId class_id, 109624d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson std::string* extension_data) { 109724d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson JDWP::JdwpError error; 109824d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson mirror::Class* c = DecodeClass(class_id, &error); 109924d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson if (c == nullptr) { 110024d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson return error; 110124d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson } 110224d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson StackHandleScope<1> hs(Thread::Current()); 110324d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson Handle<mirror::Class> klass(hs.NewHandle(c)); 110424d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson const char* data = annotations::GetSourceDebugExtension(klass); 110524d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson if (data == nullptr) { 110624d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson return JDWP::ERR_ABSENT_INFORMATION; 110724d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson } 110824d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson *extension_data = data; 110924d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson return JDWP::ERR_NONE; 111024d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson} 111124d3e46ea954cf3a35a2b57be2bf61864ee4f967Orion Hodson 1112c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetSourceFile(JDWP::RefTypeId class_id, std::string* result) { 1113c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 1114c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Class* c = DecodeClass(class_id, &error); 11154206eb5d86d3a2406361e59b2018152b2485ccedSebastien Hertz if (c == nullptr) { 1116c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 11177b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 11184206eb5d86d3a2406361e59b2018152b2485ccedSebastien Hertz const char* source_file = c->GetSourceFile(); 11194206eb5d86d3a2406361e59b2018152b2485ccedSebastien Hertz if (source_file == nullptr) { 1120b7054baf28d4d652fbd98a94b089344a31898d53Sebastien Hertz return JDWP::ERR_ABSENT_INFORMATION; 1121b7054baf28d4d652fbd98a94b089344a31898d53Sebastien Hertz } 1122c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *result = source_file; 1123436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 1124872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1125872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1126c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetObjectTag(JDWP::ObjectId object_id, uint8_t* tag) { 11279837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 1128c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 1129c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error); 1130c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (error != JDWP::ERR_NONE) { 1131c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *tag = JDWP::JT_VOID; 1132c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 1133546b986ecd09c2a498740bd8bf7127e612d94755Elliott Hughes } 1134c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *tag = TagFromObject(soa, o); 1135546b986ecd09c2a498740bd8bf7127e612d94755Elliott Hughes return JDWP::ERR_NONE; 1136872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1137872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1138aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughessize_t Dbg::GetTagWidth(JDWP::JdwpTag tag) { 1139dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes switch (tag) { 1140dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_VOID: 1141dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes return 0; 1142dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_BYTE: 1143dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_BOOLEAN: 1144dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes return 1; 1145dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_CHAR: 1146dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_SHORT: 1147dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes return 2; 1148dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_FLOAT: 1149dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_INT: 1150dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes return 4; 1151dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_ARRAY: 1152dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_OBJECT: 1153dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_STRING: 1154dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_THREAD: 1155dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_THREAD_GROUP: 1156dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_CLASS_LOADER: 1157dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_CLASS_OBJECT: 1158dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes return sizeof(JDWP::ObjectId); 1159dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_DOUBLE: 1160dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes case JDWP::JT_LONG: 1161dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes return 8; 1162dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes default: 11633d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes LOG(FATAL) << "Unknown tag " << tag; 1164dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes return -1; 1165dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes } 1166872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1167872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1168c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetArrayLength(JDWP::ObjectId array_id, int32_t* length) { 1169c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 1170c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Array* a = DecodeNonNullArray(array_id, &error); 1171c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (a == nullptr) { 1172c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 117324437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } 1174c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *length = a->GetLength(); 11753d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return JDWP::ERR_NONE; 1176872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1177872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 117888d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id, int offset, int count, JDWP::ExpandBuf* pReply) { 1179c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 1180c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Array* a = DecodeNonNullArray(array_id, &error); 11819837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers if (a == nullptr) { 1182c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 11833d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes } 118424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes 118524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes if (offset < 0 || count < 0 || offset > a->GetLength() || a->GetLength() - offset < count) { 118624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count; 11873d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return JDWP::ERR_INVALID_LENGTH; 118824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } 11891ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers JDWP::JdwpTag element_tag = BasicTagFromClass(a->GetClass()->GetComponentType()); 11901ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers expandBufAdd1(pReply, element_tag); 11913d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes expandBufAdd4BE(pReply, count); 11923d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes 11931ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers if (IsPrimitiveTag(element_tag)) { 11941ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers size_t width = GetTagWidth(element_tag); 119524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes uint8_t* dst = expandBufAddSpace(pReply, count * width); 119624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes if (width == 8) { 1197ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const uint64_t* src8 = reinterpret_cast<uint64_t*>(a->GetRawData(sizeof(uint64_t), 0)); 119824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes for (int i = 0; i < count; ++i) JDWP::Write8BE(&dst, src8[offset + i]); 119924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } else if (width == 4) { 1200ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const uint32_t* src4 = reinterpret_cast<uint32_t*>(a->GetRawData(sizeof(uint32_t), 0)); 120124437995cdac88b42e42b16d9aa121e833330999Elliott Hughes for (int i = 0; i < count; ++i) JDWP::Write4BE(&dst, src4[offset + i]); 120224437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } else if (width == 2) { 1203ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const uint16_t* src2 = reinterpret_cast<uint16_t*>(a->GetRawData(sizeof(uint16_t), 0)); 120424437995cdac88b42e42b16d9aa121e833330999Elliott Hughes for (int i = 0; i < count; ++i) JDWP::Write2BE(&dst, src2[offset + i]); 120524437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } else { 1206ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const uint8_t* src = reinterpret_cast<uint8_t*>(a->GetRawData(sizeof(uint8_t), 0)); 120724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes memcpy(dst, &src[offset * width], count * width); 120824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } 120924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } else { 12109837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 12112dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::ObjectArray<mirror::Object>* oa = a->AsObjectArray<mirror::Object>(); 121224437995cdac88b42e42b16d9aa121e833330999Elliott Hughes for (int i = 0; i < count; ++i) { 12132dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* element = oa->Get(offset + i); 12149837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers JDWP::JdwpTag specific_tag = (element != nullptr) ? TagFromObject(soa, element) 12151ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers : element_tag; 121624437995cdac88b42e42b16d9aa121e833330999Elliott Hughes expandBufAdd1(pReply, specific_tag); 121724437995cdac88b42e42b16d9aa121e833330999Elliott Hughes expandBufAddObjectId(pReply, gRegistry->Add(element)); 121824437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } 121924437995cdac88b42e42b16d9aa121e833330999Elliott Hughes } 122024437995cdac88b42e42b16d9aa121e833330999Elliott Hughes 12213d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return JDWP::ERR_NONE; 1222872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1223872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1224ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogerstemplate <typename T> 1225c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstatic void CopyArrayData(mirror::Array* a, JDWP::Request* src, int offset, int count) 1226ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers NO_THREAD_SAFETY_ANALYSIS { 1227ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers // TODO: fix when annotalysis correctly handles non-member functions. 12284b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes DCHECK(a->GetClass()->IsPrimitiveArray()); 12294b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes 1230ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers T* dst = reinterpret_cast<T*>(a->GetRawData(sizeof(T), offset)); 12314b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes for (int i = 0; i < count; ++i) { 1232c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *dst++ = src->ReadValue(sizeof(T)); 12334b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes } 12344b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes} 12354b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes 123688d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::SetArrayElements(JDWP::ObjectId array_id, int offset, int count, 1237c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::Request* request) { 1238c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 1239c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Array* dst = DecodeNonNullArray(array_id, &error); 1240c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (dst == nullptr) { 1241c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 12423d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes } 1243f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes 12444b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes if (offset < 0 || count < 0 || offset > dst->GetLength() || dst->GetLength() - offset < count) { 1245f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count; 12463d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return JDWP::ERR_INVALID_LENGTH; 1247f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes } 12481ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers JDWP::JdwpTag element_tag = BasicTagFromClass(dst->GetClass()->GetComponentType()); 1249f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes 12501ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers if (IsPrimitiveTag(element_tag)) { 12511ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers size_t width = GetTagWidth(element_tag); 1252f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes if (width == 8) { 12534b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes CopyArrayData<uint64_t>(dst, request, offset, count); 1254f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes } else if (width == 4) { 12554b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes CopyArrayData<uint32_t>(dst, request, offset, count); 1256f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes } else if (width == 2) { 12574b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes CopyArrayData<uint16_t>(dst, request, offset, count); 1258f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes } else { 12594b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes CopyArrayData<uint8_t>(dst, request, offset, count); 1260f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes } 1261f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes } else { 12624b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes mirror::ObjectArray<mirror::Object>* oa = dst->AsObjectArray<mirror::Object>(); 1263f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes for (int i = 0; i < count; ++i) { 1264c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::ObjectId id = request->ReadObjectId(); 1265c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Object* o = gRegistry->Get<mirror::Object*>(id, &error); 1266c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (error != JDWP::ERR_NONE) { 1267c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 1268436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes } 12692e1c16d9a4695e4b5cab3ed3ec95f7a88e69c79fSebastien Hertz // Check if the object's type is compatible with the array's type. 12702e1c16d9a4695e4b5cab3ed3ec95f7a88e69c79fSebastien Hertz if (o != nullptr && !o->InstanceOf(oa->GetClass()->GetComponentType())) { 12712e1c16d9a4695e4b5cab3ed3ec95f7a88e69c79fSebastien Hertz return JDWP::ERR_TYPE_MISMATCH; 12722e1c16d9a4695e4b5cab3ed3ec95f7a88e69c79fSebastien Hertz } 1273d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz oa->Set<false>(offset + i, o); 1274f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes } 1275f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes } 1276f03b8f66511a2d8cb78d306f36feb51392232a5eElliott Hughes 12773d1ca6de2ddf3d9e39755d629c896bfecd9640fdElliott Hughes return JDWP::ERR_NONE; 1278872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1279872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 12802c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien HertzJDWP::JdwpError Dbg::CreateString(const std::string& str, JDWP::ObjectId* new_string_id) { 12812c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz Thread* self = Thread::Current(); 12822c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz mirror::String* new_string = mirror::String::AllocFromModifiedUtf8(self, str.c_str()); 12832c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz if (new_string == nullptr) { 12842c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz DCHECK(self->IsExceptionPending()); 12852c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz self->ClearException(); 12862c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz LOG(ERROR) << "Could not allocate string"; 12872c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz *new_string_id = 0; 12882c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz return JDWP::ERR_OUT_OF_MEMORY; 12892c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz } 12902c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz *new_string_id = gRegistry->Add(new_string); 12912c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz return JDWP::ERR_NONE; 1292872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1293872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 12942c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien HertzJDWP::JdwpError Dbg::CreateObject(JDWP::RefTypeId class_id, JDWP::ObjectId* new_object_id) { 1295c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 1296c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Class* c = DecodeClass(class_id, &error); 1297c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (c == nullptr) { 12982c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz *new_object_id = 0; 1299c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 13007b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 13012c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz Thread* self = Thread::Current(); 130228bd2e4f151267b34b8e1eb19c489d8d547bbf5cMathieu Chartier ObjPtr<mirror::Object> new_object; 130356d5e50a7519495777f3223e21b9d73d8ceaa6adSebastien Hertz if (c->IsStringClass()) { 130456d5e50a7519495777f3223e21b9d73d8ceaa6adSebastien Hertz // Special case for java.lang.String. 130556d5e50a7519495777f3223e21b9d73d8ceaa6adSebastien Hertz gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator(); 13063aaa37bba53d6df0265793de48b4b0b57327e57ajessicahandojo new_object = mirror::String::AllocEmptyString<true>(self, allocator_type); 130756d5e50a7519495777f3223e21b9d73d8ceaa6adSebastien Hertz } else { 130856d5e50a7519495777f3223e21b9d73d8ceaa6adSebastien Hertz new_object = c->AllocObject(self); 130956d5e50a7519495777f3223e21b9d73d8ceaa6adSebastien Hertz } 13102c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz if (new_object == nullptr) { 13112c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz DCHECK(self->IsExceptionPending()); 13122c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz self->ClearException(); 1313709b070044354d9f47641f273edacaeeb0240ab7David Sehr LOG(ERROR) << "Could not allocate object of type " << mirror::Class::PrettyDescriptor(c); 13142c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz *new_object_id = 0; 13152c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz return JDWP::ERR_OUT_OF_MEMORY; 13162c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz } 131728bd2e4f151267b34b8e1eb19c489d8d547bbf5cMathieu Chartier *new_object_id = gRegistry->Add(new_object.Ptr()); 1318436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 1319872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1320872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1321bf13d36a25ec0a217fc4440c38b03d10f6c7f642Elliott Hughes/* 1322bf13d36a25ec0a217fc4440c38b03d10f6c7f642Elliott Hughes * Used by Eclipse's "Display" view to evaluate "new byte[5]" to get "(byte[]) [0, 0, 0, 0, 0]". 1323bf13d36a25ec0a217fc4440c38b03d10f6c7f642Elliott Hughes */ 132488d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::CreateArrayObject(JDWP::RefTypeId array_class_id, uint32_t length, 13252c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz JDWP::ObjectId* new_array_id) { 1326c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 1327c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Class* c = DecodeClass(array_class_id, &error); 1328c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (c == nullptr) { 13292c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz *new_array_id = 0; 1330c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 13317b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 13322c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz Thread* self = Thread::Current(); 13332c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz gc::Heap* heap = Runtime::Current()->GetHeap(); 13342c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz mirror::Array* new_array = mirror::Array::Alloc<true>(self, c, length, 13352c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz c->GetComponentSizeShift(), 13362c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz heap->GetCurrentAllocator()); 13372c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz if (new_array == nullptr) { 13382c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz DCHECK(self->IsExceptionPending()); 13392c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz self->ClearException(); 1340709b070044354d9f47641f273edacaeeb0240ab7David Sehr LOG(ERROR) << "Could not allocate array of type " << mirror::Class::PrettyDescriptor(c); 13412c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz *new_array_id = 0; 13422c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz return JDWP::ERR_OUT_OF_MEMORY; 13432c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz } 13442c3e77a0b91b2225fcdd3b34d8a734b85eec0579Sebastien Hertz *new_array_id = gRegistry->Add(new_array); 1345436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 1346872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1347872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1348c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu ChartierJDWP::FieldId Dbg::ToFieldId(const ArtField* f) { 134903181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes return static_cast<JDWP::FieldId>(reinterpret_cast<uintptr_t>(f)); 135003181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes} 135103181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 13526c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Lightstatic JDWP::MethodId ToMethodId(ArtMethod* m) 1353bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 13546c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light return static_cast<JDWP::MethodId>(reinterpret_cast<uintptr_t>(GetCanonicalMethod(m))); 135503181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes} 135603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 1357c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartierstatic ArtField* FromFieldId(JDWP::FieldId fid) 1358bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 1359c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier return reinterpret_cast<ArtField*>(static_cast<uintptr_t>(fid)); 1360aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes} 1361aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes 1362e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic ArtMethod* FromMethodId(JDWP::MethodId mid) 1363bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 1364e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier return reinterpret_cast<ArtMethod*>(static_cast<uintptr_t>(mid)); 136503181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes} 136603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 13676995c60cd6657c10811055c42661a55b10b47cefSebastien Hertzbool Dbg::MatchThread(JDWP::ObjectId expected_thread_id, Thread* event_thread) { 13686995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz CHECK(event_thread != nullptr); 13696995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz JDWP::JdwpError error; 1370e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier mirror::Object* expected_thread_peer = gRegistry->Get<mirror::Object*>( 1371e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier expected_thread_id, &error); 1372cafa08146648442ee53348c4918a4fab29e591c1Nicolas Geoffray return expected_thread_peer == event_thread->GetPeerFromOtherThread(); 13736995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz} 13746995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz 13756995c60cd6657c10811055c42661a55b10b47cefSebastien Hertzbool Dbg::MatchLocation(const JDWP::JdwpLocation& expected_location, 13766995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz const JDWP::EventLocation& event_location) { 13776995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz if (expected_location.dex_pc != event_location.dex_pc) { 13786995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz return false; 13796995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz } 1380e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m = FromMethodId(expected_location.method_id); 13816995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz return m == event_location.method; 13826995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz} 13836995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz 13843398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartierbool Dbg::MatchType(ObjPtr<mirror::Class> event_class, JDWP::RefTypeId class_id) { 1385a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz if (event_class == nullptr) { 1386a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz return false; 1387a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz } 13886995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz JDWP::JdwpError error; 13893398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier ObjPtr<mirror::Class> expected_class = DecodeClass(class_id, &error); 13906995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz CHECK(expected_class != nullptr); 13916995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz return expected_class->IsAssignableFrom(event_class); 13926995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz} 13936995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz 13946995c60cd6657c10811055c42661a55b10b47cefSebastien Hertzbool Dbg::MatchField(JDWP::RefTypeId expected_type_id, JDWP::FieldId expected_field_id, 1395c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier ArtField* event_field) { 1396c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier ArtField* expected_field = FromFieldId(expected_field_id); 13976995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz if (expected_field != event_field) { 13986995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz return false; 13996995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz } 14006995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz return Dbg::MatchType(event_field->GetDeclaringClass(), expected_type_id); 14016995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz} 14026995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz 14036995c60cd6657c10811055c42661a55b10b47cefSebastien Hertzbool Dbg::MatchInstance(JDWP::ObjectId expected_instance_id, mirror::Object* event_instance) { 14046995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz JDWP::JdwpError error; 14056995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz mirror::Object* modifier_instance = gRegistry->Get<mirror::Object*>(expected_instance_id, &error); 14066995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz return modifier_instance == event_instance; 14076995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz} 14086995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz 140990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartiervoid Dbg::SetJdwpLocation(JDWP::JdwpLocation* location, ArtMethod* m, uint32_t dex_pc) { 1410c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (m == nullptr) { 1411a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz memset(location, 0, sizeof(*location)); 141291bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes } else { 14132dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = m->GetDeclaringClass(); 1414c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers location->type_tag = GetTypeTag(c); 1415c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers location->class_id = gRegistry->AddRefType(c); 14167337631929812fb8a60b5182eba076a32d1cb851Alex Light // The RI Seems to return 0 for all obsolete methods. For compatibility we shall do the same. 14177337631929812fb8a60b5182eba076a32d1cb851Alex Light location->method_id = m->IsObsolete() ? 0 : ToMethodId(m); 1418c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers location->dex_pc = (m->IsNative() || m->IsProxyMethod()) ? static_cast<uint64_t>(-1) : dex_pc; 141991bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes } 1420d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes} 1421d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 1422c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstd::string Dbg::GetMethodName(JDWP::MethodId method_id) { 1423e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m = FromMethodId(method_id); 1424a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz if (m == nullptr) { 14252cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier return "null"; 1426a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz } 1427542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe return m->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetName(); 1428872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1429872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 14307337631929812fb8a60b5182eba076a32d1cb851Alex Lightbool Dbg::IsMethodObsolete(JDWP::MethodId method_id) { 14317337631929812fb8a60b5182eba076a32d1cb851Alex Light ArtMethod* m = FromMethodId(method_id); 14327337631929812fb8a60b5182eba076a32d1cb851Alex Light if (m == nullptr) { 14337337631929812fb8a60b5182eba076a32d1cb851Alex Light // NB Since we return 0 as MID for obsolete methods we want to default to true here. 14347337631929812fb8a60b5182eba076a32d1cb851Alex Light return true; 14357337631929812fb8a60b5182eba076a32d1cb851Alex Light } 14367337631929812fb8a60b5182eba076a32d1cb851Alex Light return m->IsObsolete(); 14377337631929812fb8a60b5182eba076a32d1cb851Alex Light} 14387337631929812fb8a60b5182eba076a32d1cb851Alex Light 1439c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersstd::string Dbg::GetFieldName(JDWP::FieldId field_id) { 1440c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier ArtField* f = FromFieldId(field_id); 1441a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz if (f == nullptr) { 14422cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier return "null"; 1443a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz } 1444a9aa0ffc2cf917be05749d1b27e7994249edb6d2Sebastien Hertz return f->GetName(); 1445a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes} 1446a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes 1447a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes/* 1448a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes * Augment the access flags for synthetic methods and fields by setting 1449a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes * the (as described by the spec) "0xf0000000 bit". Also, strip out any 1450a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes * flags not specified by the Java programming language. 1451a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes */ 1452a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughesstatic uint32_t MangleAccessFlags(uint32_t accessFlags) { 1453a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes accessFlags &= kAccJavaFlagsMask; 1454a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes if ((accessFlags & kAccSynthetic) != 0) { 1455a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes accessFlags |= 0xf0000000; 1456a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes } 1457a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes return accessFlags; 1458872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1459872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1460dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes/* 1461b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao * Circularly shifts registers so that arguments come first. Debuggers 1462b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao * expect slots to begin with arguments, but dex code places them at 1463b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao * the end. 1464dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes */ 1465e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic uint16_t MangleSlot(uint16_t slot, ArtMethod* m) 1466bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 1467bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier const DexFile::CodeItem* code_item = m->GetCodeItem(); 1468cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz if (code_item == nullptr) { 1469cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz // We should not get here for a method without code (native, proxy or abstract). Log it and 1470cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz // return the slot as is since all registers are arguments. 1471709b070044354d9f47641f273edacaeeb0240ab7David Sehr LOG(WARNING) << "Trying to mangle slot for method without code " << m->PrettyMethod(); 1472cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz return slot; 1473cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz } 1474b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao uint16_t ins_size = code_item->ins_size_; 1475b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao uint16_t locals_size = code_item->registers_size_ - ins_size; 1476b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao if (slot >= locals_size) { 1477b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao return slot - locals_size; 1478b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao } else { 1479b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao return slot + ins_size; 1480dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes } 1481dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes} 1482dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1483aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertzstatic size_t GetMethodNumArgRegistersIncludingThis(ArtMethod* method) 1484bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 1485aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertz uint32_t num_registers = ArtMethod::NumArgRegisters(method->GetShorty()); 1486aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertz if (!method->IsStatic()) { 1487aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertz ++num_registers; 1488aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertz } 1489aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertz return num_registers; 1490aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertz} 1491aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertz 1492b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao/* 1493b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao * Circularly shifts registers so that arguments come last. Reverts 1494b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao * slots to dex style argument placement. 1495b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao */ 1496e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic uint16_t DemangleSlot(uint16_t slot, ArtMethod* m, JDWP::JdwpError* error) 1497bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 1498bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier const DexFile::CodeItem* code_item = m->GetCodeItem(); 1499cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz if (code_item == nullptr) { 1500cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz // We should not get here for a method without code (native, proxy or abstract). Log it and 1501cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz // return the slot as is since all registers are arguments. 1502709b070044354d9f47641f273edacaeeb0240ab7David Sehr LOG(WARNING) << "Trying to demangle slot for method without code " 1503709b070044354d9f47641f273edacaeeb0240ab7David Sehr << m->PrettyMethod(); 1504aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertz uint16_t vreg_count = GetMethodNumArgRegistersIncludingThis(m); 1505abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz if (slot < vreg_count) { 1506abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz *error = JDWP::ERR_NONE; 1507abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return slot; 1508abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz } 1509b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao } else { 1510abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz if (slot < code_item->registers_size_) { 1511abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz uint16_t ins_size = code_item->ins_size_; 1512abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz uint16_t locals_size = code_item->registers_size_ - ins_size; 1513abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz *error = JDWP::ERR_NONE; 1514abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return (slot < ins_size) ? slot + locals_size : slot - ins_size; 1515abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz } 1516dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes } 1517abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz 1518abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz // Slot is invalid in the method. 1519709b070044354d9f47641f273edacaeeb0240ab7David Sehr LOG(ERROR) << "Invalid local slot " << slot << " for method " << m->PrettyMethod(); 1520abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz *error = JDWP::ERR_INVALID_SLOT; 1521abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return DexFile::kDexNoIndex16; 1522dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes} 1523dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 152490443477f9a0061581c420775ce3b7eeae7468bcMathieu ChartierJDWP::JdwpError Dbg::OutputDeclaredFields(JDWP::RefTypeId class_id, bool with_generic, 152590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier JDWP::ExpandBuf* pReply) { 1526c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 1527c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Class* c = DecodeClass(class_id, &error); 1528c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (c == nullptr) { 1529c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 15307b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 1531a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes 1532a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes size_t instance_field_count = c->NumInstanceFields(); 1533a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes size_t static_field_count = c->NumStaticFields(); 1534a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes 1535a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes expandBufAdd4BE(pReply, instance_field_count + static_field_count); 1536a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes 1537a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes for (size_t i = 0; i < instance_field_count + static_field_count; ++i) { 153890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier ArtField* f = (i < instance_field_count) ? c->GetInstanceField(i) : 153990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier c->GetStaticField(i - instance_field_count); 1540a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes expandBufAddFieldId(pReply, ToFieldId(f)); 154161c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier expandBufAddUtf8String(pReply, f->GetName()); 154261c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier expandBufAddUtf8String(pReply, f->GetTypeDescriptor()); 1543c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes if (with_generic) { 1544a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes static const char genericSignature[1] = ""; 1545a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes expandBufAddUtf8String(pReply, genericSignature); 1546a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes } 1547a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes expandBufAdd4BE(pReply, MangleAccessFlags(f->GetAccessFlags())); 1548a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes } 1549436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 1550a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes} 1551a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes 155288d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::OutputDeclaredMethods(JDWP::RefTypeId class_id, bool with_generic, 155300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JDWP::ExpandBuf* pReply) { 1554c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 1555c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Class* c = DecodeClass(class_id, &error); 1556c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (c == nullptr) { 1557c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 15587b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 1559a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes 156051a64d5d4fe91842cc2a5f2a412441147c145683Alex Light expandBufAdd4BE(pReply, c->NumMethods()); 1561a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes 1562e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier auto* cl = Runtime::Current()->GetClassLinker(); 1563e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier auto ptr_size = cl->GetImagePointerSize(); 156451a64d5d4fe91842cc2a5f2a412441147c145683Alex Light for (ArtMethod& m : c->GetMethods(ptr_size)) { 156551a64d5d4fe91842cc2a5f2a412441147c145683Alex Light expandBufAddMethodId(pReply, ToMethodId(&m)); 1566542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe expandBufAddUtf8String(pReply, m.GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetName()); 1567542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe expandBufAddUtf8String( 1568542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe pReply, m.GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetSignature().ToString()); 1569c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes if (with_generic) { 1570e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier const char* generic_signature = ""; 1571e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier expandBufAddUtf8String(pReply, generic_signature); 1572a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes } 157351a64d5d4fe91842cc2a5f2a412441147c145683Alex Light expandBufAdd4BE(pReply, MangleAccessFlags(m.GetAccessFlags())); 1574a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes } 1575436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 1576a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes} 1577a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes 157888d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::OutputDeclaredInterfaces(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) { 1579c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 1580f832284dd847ff077577bb5712225430bbbb3b67Mathieu Chartier Thread* self = Thread::Current(); 158119a4d374738da4dc668a078f92dbe887ff9f00d9Vladimir Marko ObjPtr<mirror::Class> c = DecodeClass(class_id, &error); 158219a4d374738da4dc668a078f92dbe887ff9f00d9Vladimir Marko if (c == nullptr) { 1583c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 15847b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes } 1585f832284dd847ff077577bb5712225430bbbb3b67Mathieu Chartier size_t interface_count = c->NumDirectInterfaces(); 1586a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes expandBufAdd4BE(pReply, interface_count); 1587a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes for (size_t i = 0; i < interface_count; ++i) { 158819a4d374738da4dc668a078f92dbe887ff9f00d9Vladimir Marko ObjPtr<mirror::Class> interface = mirror::Class::GetDirectInterface(self, c, i); 158919a4d374738da4dc668a078f92dbe887ff9f00d9Vladimir Marko DCHECK(interface != nullptr); 159019a4d374738da4dc668a078f92dbe887ff9f00d9Vladimir Marko expandBufAddRefTypeId(pReply, gRegistry->AddRefType(interface)); 1591a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes } 1592436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes return JDWP::ERR_NONE; 1593872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1594872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1595c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersvoid Dbg::OutputLineTable(JDWP::RefTypeId, JDWP::MethodId method_id, JDWP::ExpandBuf* pReply) { 159603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes struct DebugCallbackContext { 159703181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes int numItems; 159803181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes JDWP::ExpandBuf* pReply; 159903181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 1600b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky static bool Callback(void* context, const DexFile::PositionInfo& entry) { 160103181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes DebugCallbackContext* pContext = reinterpret_cast<DebugCallbackContext*>(context); 1602b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky expandBufAdd8BE(pContext->pReply, entry.address_); 1603b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky expandBufAdd4BE(pContext->pReply, entry.line_); 160403181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes pContext->numItems++; 1605f2910eef247b45ce1d489e323b36b5de6b6157aaSebastien Hertz return false; 160603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes } 160703181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes }; 1608e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m = FromMethodId(method_id); 1609bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier const DexFile::CodeItem* code_item = m->GetCodeItem(); 161003181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes uint64_t start, end; 1611cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz if (code_item == nullptr) { 1612cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz DCHECK(m->IsNative() || m->IsProxyMethod()); 161303181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes start = -1; 161403181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes end = -1; 161503181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes } else { 161603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes start = 0; 161714f0db92225d34622fa5cb1a6dc9287334aaf6c7jeffhao // Return the index of the last instruction 1618cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz end = code_item->insns_size_in_code_units_ - 1; 161903181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes } 162003181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 162103181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes expandBufAdd8BE(pReply, start); 162203181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes expandBufAdd8BE(pReply, end); 162303181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 162403181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes // Add numLines later 162503181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes size_t numLinesOffset = expandBufGetLength(pReply); 162603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes expandBufAdd4BE(pReply, 0); 162703181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 162803181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes DebugCallbackContext context; 162903181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes context.numItems = 0; 163003181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes context.pReply = pReply; 163103181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 1632cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz if (code_item != nullptr) { 1633b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky m->GetDexFile()->DecodeDebugPositionInfo(code_item, DebugCallbackContext::Callback, &context); 1634cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz } 163503181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 163603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes JDWP::Set4BE(expandBufGetBuffer(pReply) + numLinesOffset, context.numItems); 1637872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1638872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1639bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartiervoid Dbg::OutputVariableTable(JDWP::RefTypeId, JDWP::MethodId method_id, bool with_generic, 1640bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier JDWP::ExpandBuf* pReply) { 1641dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes struct DebugCallbackContext { 1642e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* method; 1643dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes JDWP::ExpandBuf* pReply; 1644c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes size_t variable_count; 1645c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes bool with_generic; 1646dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1647b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky static void Callback(void* context, const DexFile::LocalInfo& entry) 1648bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 1649dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes DebugCallbackContext* pContext = reinterpret_cast<DebugCallbackContext*>(context); 1650dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1651b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky uint16_t slot = entry.reg_; 1652bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier VLOG(jdwp) << StringPrintf(" %2zd: %d(%d) '%s' '%s' '%s' actual slot=%d mangled slot=%d", 1653b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky pContext->variable_count, entry.start_address_, 1654b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky entry.end_address_ - entry.start_address_, 1655b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky entry.name_, entry.descriptor_, entry.signature_, slot, 1656bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier MangleSlot(slot, pContext->method)); 1657dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1658b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao slot = MangleSlot(slot, pContext->method); 165968fdbd07fc2b8856905e06f3cc945b046c3bfcd3Elliott Hughes 1660b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky expandBufAdd8BE(pContext->pReply, entry.start_address_); 1661b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky expandBufAddUtf8String(pContext->pReply, entry.name_); 1662b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky expandBufAddUtf8String(pContext->pReply, entry.descriptor_); 1663c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes if (pContext->with_generic) { 1664b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky expandBufAddUtf8String(pContext->pReply, entry.signature_); 1665dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes } 1666b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky expandBufAdd4BE(pContext->pReply, entry.end_address_- entry.start_address_); 1667dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes expandBufAdd4BE(pContext->pReply, slot); 1668dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1669c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes ++pContext->variable_count; 1670dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes } 1671dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes }; 1672e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m = FromMethodId(method_id); 1673dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1674c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes // arg_count considers doubles and longs to take 2 units. 1675c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes // variable_count considers everything to take 1 unit. 1676aef0c91e0b03f26c3947ccf2608d92ae6eae632dSebastien Hertz expandBufAdd4BE(pReply, GetMethodNumArgRegistersIncludingThis(m)); 1677dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1678c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes // We don't know the total number of variables yet, so leave a blank and update it later. 1679c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes size_t variable_count_offset = expandBufGetLength(pReply); 1680dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes expandBufAdd4BE(pReply, 0); 1681dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1682dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes DebugCallbackContext context; 1683b7cefc7f5cac99a62fd4e662c1bdeec750434e28Jeff Hao context.method = m; 1684dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes context.pReply = pReply; 1685c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes context.variable_count = 0; 1686c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes context.with_generic = with_generic; 1687dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1688bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier const DexFile::CodeItem* code_item = m->GetCodeItem(); 1689cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz if (code_item != nullptr) { 1690b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky m->GetDexFile()->DecodeDebugLocalInfo( 1691b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky code_item, m->IsStatic(), m->GetDexMethodIndex(), DebugCallbackContext::Callback, 1692bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier &context); 1693cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz } 1694dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 1695c5b734a27a64c81590015dd12a7901c396818a99Elliott Hughes JDWP::Set4BE(expandBufGetBuffer(pReply) + variable_count_offset, context.variable_count); 1696872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1697872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1698579b02416e05e32e535126e1ed61613a2cdb030eJeff Haovoid Dbg::OutputMethodReturnValue(JDWP::MethodId method_id, const JValue* return_value, 1699579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao JDWP::ExpandBuf* pReply) { 1700e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m = FromMethodId(method_id); 1701bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier JDWP::JdwpTag tag = BasicTagFromDescriptor(m->GetShorty()); 1702579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao OutputJValue(tag, return_value, pReply); 1703579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao} 1704579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao 17053f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertzvoid Dbg::OutputFieldValue(JDWP::FieldId field_id, const JValue* field_value, 17063f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz JDWP::ExpandBuf* pReply) { 1707c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier ArtField* f = FromFieldId(field_id); 170861c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier JDWP::JdwpTag tag = BasicTagFromDescriptor(f->GetTypeDescriptor()); 17093f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz OutputJValue(tag, field_value, pReply); 17103f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz} 17113f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz 17129777ba230c83a0edcbda2cf7b208339e77bf171bElliott HughesJDWP::JdwpError Dbg::GetBytecodes(JDWP::RefTypeId, JDWP::MethodId method_id, 1713c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers std::vector<uint8_t>* bytecodes) { 1714e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m = FromMethodId(method_id); 1715c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (m == nullptr) { 17169777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes return JDWP::ERR_INVALID_METHODID; 17179777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes } 1718bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier const DexFile::CodeItem* code_item = m->GetCodeItem(); 17199777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes size_t byte_count = code_item->insns_size_in_code_units_ * 2; 17209777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes const uint8_t* begin = reinterpret_cast<const uint8_t*>(code_item->insns_); 17219777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes const uint8_t* end = begin + byte_count; 17229777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes for (const uint8_t* p = begin; p != end; ++p) { 1723c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers bytecodes->push_back(*p); 17249777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes } 17259777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes return JDWP::ERR_NONE; 17269777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes} 17279777ba230c83a0edcbda2cf7b208339e77bf171bElliott Hughes 172888d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpTag Dbg::GetFieldBasicTag(JDWP::FieldId field_id) { 172961c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier return BasicTagFromDescriptor(FromFieldId(field_id)->GetTypeDescriptor()); 1730872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1731872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 173288d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpTag Dbg::GetStaticFieldBasicTag(JDWP::FieldId field_id) { 173361c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier return BasicTagFromDescriptor(FromFieldId(field_id)->GetTypeDescriptor()); 1734872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1735872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 173605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertzstatic JValue GetArtFieldValue(ArtField* f, mirror::Object* o) 1737bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 173805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz Primitive::Type fieldType = f->GetTypeAsPrimitiveType(); 173905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz JValue field_value; 174005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz switch (fieldType) { 174105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimBoolean: 174205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz field_value.SetZ(f->GetBoolean(o)); 174305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz return field_value; 174405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz 174505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimByte: 174605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz field_value.SetB(f->GetByte(o)); 174705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz return field_value; 174805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz 174905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimChar: 175005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz field_value.SetC(f->GetChar(o)); 175105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz return field_value; 175205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz 175305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimShort: 175405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz field_value.SetS(f->GetShort(o)); 175505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz return field_value; 175605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz 175705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimInt: 175805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimFloat: 175905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz // Int and Float must be treated as 32-bit values in JDWP. 176005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz field_value.SetI(f->GetInt(o)); 176105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz return field_value; 176205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz 176305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimLong: 176405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimDouble: 176505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz // Long and Double must be treated as 64-bit values in JDWP. 176605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz field_value.SetJ(f->GetLong(o)); 176705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz return field_value; 176805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz 176905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimNot: 17701cc62e4ea24828fdb3f3da0b8603f0b107d09a04Mathieu Chartier field_value.SetL(f->GetObject(o).Ptr()); 177105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz return field_value; 177205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz 177305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimVoid: 177405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz LOG(FATAL) << "Attempt to read from field of type 'void'"; 177505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz UNREACHABLE(); 177605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz } 177705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz LOG(FATAL) << "Attempt to read from field of unknown type"; 177805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz UNREACHABLE(); 177905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz} 178005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz 178188d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughesstatic JDWP::JdwpError GetFieldValueImpl(JDWP::RefTypeId ref_type_id, JDWP::ObjectId object_id, 178288d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes JDWP::FieldId field_id, JDWP::ExpandBuf* pReply, 178300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool is_static) 1784bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 1785c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 1786c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Class* c = DecodeClass(ref_type_id, &error); 1787c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (ref_type_id != 0 && c == nullptr) { 1788c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 17890cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes } 17900cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes 1791de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao Thread* self = Thread::Current(); 1792de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao StackHandleScope<2> hs(self); 1793de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao MutableHandle<mirror::Object> 1794de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao o(hs.NewHandle(Dbg::GetObjectRegistry()->Get<mirror::Object*>(object_id, &error))); 1795fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe if ((!is_static && o == nullptr) || error != JDWP::ERR_NONE) { 17963f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 17973f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes } 1798c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier ArtField* f = FromFieldId(field_id); 17990cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes 18002dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* receiver_class = c; 1801fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe if (receiver_class == nullptr && o != nullptr) { 18020cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes receiver_class = o->GetClass(); 18030cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes } 1804de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao 18052cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier // TODO: should we give up now if receiver_class is null? 1806c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (receiver_class != nullptr && !f->GetDeclaringClass()->IsAssignableFrom(receiver_class)) { 1807709b070044354d9f47641f273edacaeeb0240ab7David Sehr LOG(INFO) << "ERR_INVALID_FIELDID: " << f->PrettyField() << " " 1808709b070044354d9f47641f273edacaeeb0240ab7David Sehr << receiver_class->PrettyClass(); 18093f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes return JDWP::ERR_INVALID_FIELDID; 18103f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes } 1811aed4be94da51b4fbb54c728151f0daf11535f6abElliott Hughes 1812de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao // Ensure the field's class is initialized. 1813de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao Handle<mirror::Class> klass(hs.NewHandle(f->GetDeclaringClass())); 1814de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(self, klass, true, false)) { 1815709b070044354d9f47641f273edacaeeb0240ab7David Sehr LOG(WARNING) << "Not able to initialize class for SetValues: " 1816709b070044354d9f47641f273edacaeeb0240ab7David Sehr << mirror::Class::PrettyClass(klass.Get()); 1817de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao } 1818de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao 18190cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes // The RI only enforces the static/non-static mismatch in one direction. 18200cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes // TODO: should we change the tests and check both? 18210cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes if (is_static) { 18220cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes if (!f->IsStatic()) { 18230cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes return JDWP::ERR_INVALID_FIELDID; 18240cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes } 18250cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes } else { 18260cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes if (f->IsStatic()) { 182705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz LOG(WARNING) << "Ignoring non-nullptr receiver for ObjectReference.GetValues" 1828709b070044354d9f47641f273edacaeeb0240ab7David Sehr << " on static field " << f->PrettyField(); 18290cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes } 18300cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes } 18310dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao if (f->IsStatic()) { 1832de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao o.Assign(f->GetDeclaringClass()); 18330dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao } 18340cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes 1835de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao JValue field_value(GetArtFieldValue(f, o.Get())); 183661c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier JDWP::JdwpTag tag = BasicTagFromDescriptor(f->GetTypeDescriptor()); 1837579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao Dbg::OutputJValue(tag, &field_value, pReply); 18383f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes return JDWP::ERR_NONE; 1839872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1840872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 184188d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::GetFieldValue(JDWP::ObjectId object_id, JDWP::FieldId field_id, 184200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JDWP::ExpandBuf* pReply) { 184388d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes return GetFieldValueImpl(0, object_id, field_id, pReply, false); 18443f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes} 18453f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes 1846c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetStaticFieldValue(JDWP::RefTypeId ref_type_id, JDWP::FieldId field_id, 1847c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::ExpandBuf* pReply) { 184888d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes return GetFieldValueImpl(ref_type_id, 0, field_id, pReply, true); 18493f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes} 18503f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes 185105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertzstatic JDWP::JdwpError SetArtFieldValue(ArtField* f, mirror::Object* o, uint64_t value, int width) 1852bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 185305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz Primitive::Type fieldType = f->GetTypeAsPrimitiveType(); 185405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz // Debugging only happens at runtime so we know we are not running in a transaction. 185505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz static constexpr bool kNoTransactionMode = false; 185605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz switch (fieldType) { 185705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimBoolean: 185805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz CHECK_EQ(width, 1); 185905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz f->SetBoolean<kNoTransactionMode>(o, static_cast<uint8_t>(value)); 186005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz return JDWP::ERR_NONE; 186105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz 186205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimByte: 186305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz CHECK_EQ(width, 1); 186405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz f->SetByte<kNoTransactionMode>(o, static_cast<uint8_t>(value)); 186505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz return JDWP::ERR_NONE; 186605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz 186705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimChar: 186805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz CHECK_EQ(width, 2); 186905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz f->SetChar<kNoTransactionMode>(o, static_cast<uint16_t>(value)); 187005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz return JDWP::ERR_NONE; 187105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz 187205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimShort: 187305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz CHECK_EQ(width, 2); 187405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz f->SetShort<kNoTransactionMode>(o, static_cast<int16_t>(value)); 187505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz return JDWP::ERR_NONE; 187605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz 187705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimInt: 187805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimFloat: 187905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz CHECK_EQ(width, 4); 188005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz // Int and Float must be treated as 32-bit values in JDWP. 188105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz f->SetInt<kNoTransactionMode>(o, static_cast<int32_t>(value)); 188205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz return JDWP::ERR_NONE; 188305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz 188405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimLong: 188505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimDouble: 188605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz CHECK_EQ(width, 8); 188705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz // Long and Double must be treated as 64-bit values in JDWP. 188805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz f->SetLong<kNoTransactionMode>(o, value); 188905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz return JDWP::ERR_NONE; 189005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz 189105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimNot: { 189205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz JDWP::JdwpError error; 189305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz mirror::Object* v = Dbg::GetObjectRegistry()->Get<mirror::Object*>(value, &error); 189405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz if (error != JDWP::ERR_NONE) { 189505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz return JDWP::ERR_INVALID_OBJECT; 189605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz } 189705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz if (v != nullptr) { 18983398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier ObjPtr<mirror::Class> field_type; 189905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz { 190005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz StackHandleScope<2> hs(Thread::Current()); 190105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz HandleWrapper<mirror::Object> h_v(hs.NewHandleWrapper(&v)); 190205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz HandleWrapper<mirror::Object> h_o(hs.NewHandleWrapper(&o)); 190305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz field_type = f->GetType<true>(); 190405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz } 190505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz if (!field_type->IsAssignableFrom(v->GetClass())) { 190605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz return JDWP::ERR_INVALID_OBJECT; 190705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz } 190805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz } 190905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz f->SetObject<kNoTransactionMode>(o, v); 191005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz return JDWP::ERR_NONE; 191105c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz } 191205c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz 191305c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz case Primitive::kPrimVoid: 191405c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz LOG(FATAL) << "Attempt to write to field of type 'void'"; 191505c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz UNREACHABLE(); 191605c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz } 191705c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz LOG(FATAL) << "Attempt to write to field of unknown type"; 191805c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz UNREACHABLE(); 191905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz} 192005c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz 192188d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughesstatic JDWP::JdwpError SetFieldValueImpl(JDWP::ObjectId object_id, JDWP::FieldId field_id, 192200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers uint64_t value, int width, bool is_static) 1923bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 1924c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 1925de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao Thread* self = Thread::Current(); 1926de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao StackHandleScope<2> hs(self); 1927de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao MutableHandle<mirror::Object> 1928de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao o(hs.NewHandle(Dbg::GetObjectRegistry()->Get<mirror::Object*>(object_id, &error))); 1929fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe if ((!is_static && o == nullptr) || error != JDWP::ERR_NONE) { 19303f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 19313f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes } 1932c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier ArtField* f = FromFieldId(field_id); 19330cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes 1934de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao // Ensure the field's class is initialized. 1935de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao Handle<mirror::Class> klass(hs.NewHandle(f->GetDeclaringClass())); 1936de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(self, klass, true, false)) { 1937709b070044354d9f47641f273edacaeeb0240ab7David Sehr LOG(WARNING) << "Not able to initialize class for SetValues: " 1938709b070044354d9f47641f273edacaeeb0240ab7David Sehr << mirror::Class::PrettyClass(klass.Get()); 1939de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao } 1940de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao 19410cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes // The RI only enforces the static/non-static mismatch in one direction. 19420cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes // TODO: should we change the tests and check both? 19430cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes if (is_static) { 19440cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes if (!f->IsStatic()) { 19450cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes return JDWP::ERR_INVALID_FIELDID; 19460cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes } 19470cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes } else { 19480cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes if (f->IsStatic()) { 194905c26b30843dd8283c703356e75d51726e8b8e3aSebastien Hertz LOG(WARNING) << "Ignoring non-nullptr receiver for ObjectReference.SetValues" 1950709b070044354d9f47641f273edacaeeb0240ab7David Sehr << " on static field " << f->PrettyField(); 19510cf7433fd2a93b7f83e8b2ac91d0d1b4f0e7d0c9Elliott Hughes } 19523f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes } 19530dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao if (f->IsStatic()) { 1954de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao o.Assign(f->GetDeclaringClass()); 19550dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao } 1956de19a25625823496bcf8f92352f709c7a3924bfaJeff Hao return SetArtFieldValue(f, o.Get(), value, width); 1957872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1958872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 195988d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::SetFieldValue(JDWP::ObjectId object_id, JDWP::FieldId field_id, uint64_t value, 196000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers int width) { 196188d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes return SetFieldValueImpl(object_id, field_id, value, width, false); 1962872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1963872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 196488d630950cb5c6a1cb6457ce03a17c074ae13628Elliott HughesJDWP::JdwpError Dbg::SetStaticFieldValue(JDWP::FieldId field_id, uint64_t value, int width) { 196588d630950cb5c6a1cb6457ce03a17c074ae13628Elliott Hughes return SetFieldValueImpl(0, field_id, value, width, true); 1966872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1967872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1968b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien HertzJDWP::JdwpError Dbg::StringToUtf8(JDWP::ObjectId string_id, std::string* str) { 1969c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 1970b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz mirror::Object* obj = gRegistry->Get<mirror::Object*>(string_id, &error); 1971b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz if (error != JDWP::ERR_NONE) { 1972b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz return error; 1973b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz } 1974b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz if (obj == nullptr) { 1975b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz return JDWP::ERR_INVALID_OBJECT; 1976b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz } 1977b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz { 1978b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz ScopedObjectAccessUnchecked soa(Thread::Current()); 19790795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ObjPtr<mirror::Class> java_lang_String = 19800795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier soa.Decode<mirror::Class>(WellKnownClasses::java_lang_String); 1981b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz if (!java_lang_String->IsAssignableFrom(obj->GetClass())) { 1982b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz // This isn't a string. 1983b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz return JDWP::ERR_INVALID_STRING; 1984b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz } 1985b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz } 1986b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz *str = obj->AsString()->ToModifiedUtf8(); 1987b0b0b496125c16620e99ea4e4a05693c281eccf1Sebastien Hertz return JDWP::ERR_NONE; 1988872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 1989872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 1990579b02416e05e32e535126e1ed61613a2cdb030eJeff Haovoid Dbg::OutputJValue(JDWP::JdwpTag tag, const JValue* return_value, JDWP::ExpandBuf* pReply) { 1991579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao if (IsPrimitiveTag(tag)) { 1992579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao expandBufAdd1(pReply, tag); 1993579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao if (tag == JDWP::JT_BOOLEAN || tag == JDWP::JT_BYTE) { 1994579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao expandBufAdd1(pReply, return_value->GetI()); 1995579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao } else if (tag == JDWP::JT_CHAR || tag == JDWP::JT_SHORT) { 1996579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao expandBufAdd2BE(pReply, return_value->GetI()); 1997579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao } else if (tag == JDWP::JT_FLOAT || tag == JDWP::JT_INT) { 1998579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao expandBufAdd4BE(pReply, return_value->GetI()); 1999579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao } else if (tag == JDWP::JT_DOUBLE || tag == JDWP::JT_LONG) { 2000579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao expandBufAdd8BE(pReply, return_value->GetJ()); 2001579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao } else { 2002579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao CHECK_EQ(tag, JDWP::JT_VOID); 2003579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao } 2004579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao } else { 20059837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 2006579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao mirror::Object* value = return_value->GetL(); 20079837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers expandBufAdd1(pReply, TagFromObject(soa, value)); 2008579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao expandBufAddObjectId(pReply, gRegistry->Add(value)); 2009579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao } 2010579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao} 2011579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao 2012c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetThreadName(JDWP::ObjectId thread_id, std::string* name) { 2013a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao ScopedObjectAccessUnchecked soa(Thread::Current()); 2014c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 20154b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain DecodeThread(soa, thread_id, &error); 2016221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error != JDWP::ERR_NONE && error != JDWP::ERR_THREAD_NOT_ALIVE) { 2017221229cb523f849f165fdafbf9785010963715daElliott Hughes return error; 2018a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes } 2019221229cb523f849f165fdafbf9785010963715daElliott Hughes 2020221229cb523f849f165fdafbf9785010963715daElliott Hughes // We still need to report the zombie threads' names, so we can't just call Thread::GetThreadName. 2021c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Object* thread_object = gRegistry->Get<mirror::Object*>(thread_id, &error); 2022c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers CHECK(thread_object != nullptr) << error; 2023c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier ArtField* java_lang_Thread_name_field = 202408883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe jni::DecodeArtField(WellKnownClasses::java_lang_Thread_name); 2025f8ac97f94aad9ce2d324c2c7c21dde3abf13315bMathieu Chartier ObjPtr<mirror::String> s(java_lang_Thread_name_field->GetObject(thread_object)->AsString()); 2026c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (s != nullptr) { 2027c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *name = s->ToModifiedUtf8(); 2028221229cb523f849f165fdafbf9785010963715daElliott Hughes } 2029221229cb523f849f165fdafbf9785010963715daElliott Hughes return JDWP::ERR_NONE; 2030872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2031872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2032221229cb523f849f165fdafbf9785010963715daElliott HughesJDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply) { 2033a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz ScopedObjectAccessUnchecked soa(Thread::Current()); 2034c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 2035c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Object* thread_object = gRegistry->Get<mirror::Object*>(thread_id, &error); 2036c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (error != JDWP::ERR_NONE) { 20372435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 20382435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 2039268764da8022cafa5661c5b514eaa343c5257e57Mathieu Chartier ScopedAssertNoThreadSuspension ants("Debugger: GetThreadGroup"); 20402435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // Okay, so it's an object, but is it actually a thread? 20414b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain DecodeThread(soa, thread_id, &error); 2042221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error == JDWP::ERR_THREAD_NOT_ALIVE) { 2043221229cb523f849f165fdafbf9785010963715daElliott Hughes // Zombie threads are in the null group. 2044221229cb523f849f165fdafbf9785010963715daElliott Hughes expandBufAddObjectId(pReply, JDWP::ObjectId(0)); 204552d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz error = JDWP::ERR_NONE; 204652d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz } else if (error == JDWP::ERR_NONE) { 20470795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(WellKnownClasses::java_lang_Thread); 204852d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz CHECK(c != nullptr); 204908883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe ArtField* f = jni::DecodeArtField(WellKnownClasses::java_lang_Thread_group); 2050b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi CHECK(f != nullptr); 20513398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier ObjPtr<mirror::Object> group = f->GetObject(thread_object); 2052b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi CHECK(group != nullptr); 205352d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz JDWP::ObjectId thread_group_id = gRegistry->Add(group); 205452d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz expandBufAddObjectId(pReply, thread_group_id); 20552435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 205652d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz return error; 2057872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2058872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2059a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertzstatic mirror::Object* DecodeThreadGroup(ScopedObjectAccessUnchecked& soa, 2060a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz JDWP::ObjectId thread_group_id, JDWP::JdwpError* error) 2061bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 20626995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz mirror::Object* thread_group = Dbg::GetObjectRegistry()->Get<mirror::Object*>(thread_group_id, 20636995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz error); 2064a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz if (*error != JDWP::ERR_NONE) { 2065a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz return nullptr; 2066a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz } 2067a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz if (thread_group == nullptr) { 2068a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz *error = JDWP::ERR_INVALID_OBJECT; 2069a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz return nullptr; 2070a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz } 20710795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ObjPtr<mirror::Class> c = 20720795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier soa.Decode<mirror::Class>(WellKnownClasses::java_lang_ThreadGroup); 2073a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz CHECK(c != nullptr); 2074a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz if (!c->IsAssignableFrom(thread_group->GetClass())) { 2075a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz // This is not a java.lang.ThreadGroup. 2076a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz *error = JDWP::ERR_INVALID_THREAD_GROUP; 2077a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz return nullptr; 2078a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz } 2079a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz *error = JDWP::ERR_NONE; 2080a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz return thread_group; 2081a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz} 2082a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz 2083a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien HertzJDWP::JdwpError Dbg::GetThreadGroupName(JDWP::ObjectId thread_group_id, JDWP::ExpandBuf* pReply) { 2084a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz ScopedObjectAccessUnchecked soa(Thread::Current()); 2085c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 2086a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz mirror::Object* thread_group = DecodeThreadGroup(soa, thread_group_id, &error); 2087a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz if (error != JDWP::ERR_NONE) { 2088a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz return error; 2089a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz } 2090268764da8022cafa5661c5b514eaa343c5257e57Mathieu Chartier ScopedAssertNoThreadSuspension ants("Debugger: GetThreadGroupName"); 209108883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe ArtField* f = jni::DecodeArtField(WellKnownClasses::java_lang_ThreadGroup_name); 2092c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers CHECK(f != nullptr); 20933398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier ObjPtr<mirror::String> s = f->GetObject(thread_group)->AsString(); 2094a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz 2095a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz std::string thread_group_name(s->ToModifiedUtf8()); 2096a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz expandBufAddUtf8String(pReply, thread_group_name); 2097a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz return JDWP::ERR_NONE; 2098872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2099872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2100a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien HertzJDWP::JdwpError Dbg::GetThreadGroupParent(JDWP::ObjectId thread_group_id, JDWP::ExpandBuf* pReply) { 21019837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 2102c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 2103a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz mirror::Object* thread_group = DecodeThreadGroup(soa, thread_group_id, &error); 2104a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz if (error != JDWP::ERR_NONE) { 2105a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz return error; 2106a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz } 21073398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier ObjPtr<mirror::Object> parent; 21082d5f39ed5aeaeb7ca22b07b4c6e8c56348ef8893Mathieu Chartier { 2109268764da8022cafa5661c5b514eaa343c5257e57Mathieu Chartier ScopedAssertNoThreadSuspension ants("Debugger: GetThreadGroupParent"); 211008883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe ArtField* f = jni::DecodeArtField(WellKnownClasses::java_lang_ThreadGroup_parent); 21112d5f39ed5aeaeb7ca22b07b4c6e8c56348ef8893Mathieu Chartier CHECK(f != nullptr); 21122d5f39ed5aeaeb7ca22b07b4c6e8c56348ef8893Mathieu Chartier parent = f->GetObject(thread_group); 21132d5f39ed5aeaeb7ca22b07b4c6e8c56348ef8893Mathieu Chartier } 2114a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz JDWP::ObjectId parent_group_id = gRegistry->Add(parent); 2115a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz expandBufAddObjectId(pReply, parent_group_id); 2116a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz return JDWP::ERR_NONE; 2117872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2118872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 211908883debd927d18c9ecf66683a2a11aa98165656Andreas Gampestatic void GetChildThreadGroups(mirror::Object* thread_group, 2120a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz std::vector<JDWP::ObjectId>* child_thread_group_ids) 2121bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 2122a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz CHECK(thread_group != nullptr); 2123a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz 2124464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak // Get the int "ngroups" count of this thread group... 212508883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe ArtField* ngroups_field = jni::DecodeArtField(WellKnownClasses::java_lang_ThreadGroup_ngroups); 2126464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak CHECK(ngroups_field != nullptr); 2127464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak const int32_t size = ngroups_field->GetInt(thread_group); 2128464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak if (size == 0) { 2129464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak return; 2130e49e195c4bc2f20df0289c0bbb46f56839308ddeSebastien Hertz } 2131a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz 2132464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak // Get the ThreadGroup[] "groups" out of this thread group... 213308883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe ArtField* groups_field = jni::DecodeArtField(WellKnownClasses::java_lang_ThreadGroup_groups); 21343398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier ObjPtr<mirror::Object> groups_array = groups_field->GetObject(thread_group); 2135464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak 2136464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak CHECK(groups_array != nullptr); 2137464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak CHECK(groups_array->IsObjectArray()); 2138464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak 21393398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier ObjPtr<mirror::ObjectArray<mirror::Object>> groups_array_as_array = 2140464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak groups_array->AsObjectArray<mirror::Object>(); 2141a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz 2142a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz // Copy the first 'size' elements out of the array into the result. 21436995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz ObjectRegistry* registry = Dbg::GetObjectRegistry(); 2144a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz for (int32_t i = 0; i < size; ++i) { 2145464595f53abe4370ee6f589eb472e2036e39bce7Przemyslaw Szczepaniak child_thread_group_ids->push_back(registry->Add(groups_array_as_array->Get(i))); 2146a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz } 2147a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz} 2148a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz 2149a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien HertzJDWP::JdwpError Dbg::GetThreadGroupChildren(JDWP::ObjectId thread_group_id, 2150a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz JDWP::ExpandBuf* pReply) { 215100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 2152a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz JDWP::JdwpError error; 2153a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz mirror::Object* thread_group = DecodeThreadGroup(soa, thread_group_id, &error); 2154a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz if (error != JDWP::ERR_NONE) { 2155a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz return error; 2156a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz } 2157a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz 2158a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz // Add child threads. 2159a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz { 2160a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz std::vector<JDWP::ObjectId> child_thread_ids; 2161a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz GetThreads(thread_group, &child_thread_ids); 2162a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz expandBufAdd4BE(pReply, child_thread_ids.size()); 2163a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz for (JDWP::ObjectId child_thread_id : child_thread_ids) { 2164a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz expandBufAddObjectId(pReply, child_thread_id); 2165a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz } 2166a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz } 2167a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz 2168a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz // Add child thread groups. 2169a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz { 2170a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz std::vector<JDWP::ObjectId> child_thread_groups_ids; 217108883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe GetChildThreadGroups(thread_group, &child_thread_groups_ids); 2172a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz expandBufAdd4BE(pReply, child_thread_groups_ids.size()); 2173a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz for (JDWP::ObjectId child_thread_group_id : child_thread_groups_ids) { 2174a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz expandBufAddObjectId(pReply, child_thread_group_id); 2175a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz } 2176a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz } 2177a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz 2178a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz return JDWP::ERR_NONE; 2179872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2180872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2181a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien HertzJDWP::ObjectId Dbg::GetSystemThreadGroupId() { 2182a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertz ScopedObjectAccessUnchecked soa(Thread::Current()); 218308883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe ArtField* f = jni::DecodeArtField(WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup); 21843398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier ObjPtr<mirror::Object> group = f->GetObject(f->GetDeclaringClass()); 2185365c10235438607541fa2259a5fec48061b90bd8Ian Rogers return gRegistry->Add(group); 2186872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2187872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2188920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff HaoJDWP::JdwpThreadStatus Dbg::ToJdwpThreadStatus(ThreadState state) { 2189920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao switch (state) { 2190920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kBlocked: 2191920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao return JDWP::TS_MONITOR; 2192920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kNative: 2193920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kRunnable: 2194920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kSuspended: 2195920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao return JDWP::TS_RUNNING; 2196920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kSleeping: 2197920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao return JDWP::TS_SLEEPING; 2198920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kStarting: 2199920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kTerminated: 2200920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao return JDWP::TS_ZOMBIE; 2201920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kTimedWaiting: 2202bae182cbc6adc8796154162a87fc54ae804e0469Sebastien Hertz case kWaitingForCheckPointsToRun: 2203920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingForDebuggerSend: 2204920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingForDebuggerSuspension: 2205920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingForDebuggerToAttach: 2206138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz case kWaitingForDeoptimization: 2207920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingForGcToComplete: 2208b43390cb87eace4a017f672d66cfb20fb9e76aa1Mathieu Chartier case kWaitingForGetObjectsAllocated: 2209920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingForJniOnLoad: 2210bae182cbc6adc8796154162a87fc54ae804e0469Sebastien Hertz case kWaitingForMethodTracingStart: 2211920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingForSignalCatcherOutput: 22120c8c303c20cdaaf54d26e45cc17dc5afb820d8efHiroshi Yamauchi case kWaitingForVisitObjects: 2213920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingInMainDebuggerLoop: 2214920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingInMainSignalCatcherLoop: 2215920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaitingPerformingGc: 221690ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartier case kWaitingWeakGcRootRead: 221776f55b030d2517d434f227bee2363c3fb760e5c6Hiroshi Yamauchi case kWaitingForGcThreadFlip: 2218920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao case kWaiting: 2219920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao return JDWP::TS_WAIT; 2220920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao // Don't add a 'default' here so the compiler can spot incompatible enum changes. 2221920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao } 2222920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao LOG(FATAL) << "Unknown thread state: " << state; 2223920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao return JDWP::TS_ZOMBIE; 2224920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao} 2225920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao 222652d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien HertzJDWP::JdwpError Dbg::GetThreadStatus(JDWP::ObjectId thread_id, JDWP::JdwpThreadStatus* pThreadStatus, 222752d131d8e71ae9ea915ea84a3f95d49547e8e661Sebastien Hertz JDWP::JdwpSuspendStatus* pSuspendStatus) { 222800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 2229499c5133d361e7c659fc38e5ccfeb1280a7996f5Elliott Hughes 22309e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes *pSuspendStatus = JDWP::SUSPEND_STATUS_NOT_SUSPENDED; 22319e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes 2232c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 2233c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers Thread* thread = DecodeThread(soa, thread_id, &error); 2234221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error != JDWP::ERR_NONE) { 2235221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error == JDWP::ERR_THREAD_NOT_ALIVE) { 2236221229cb523f849f165fdafbf9785010963715daElliott Hughes *pThreadStatus = JDWP::TS_ZOMBIE; 2237221229cb523f849f165fdafbf9785010963715daElliott Hughes return JDWP::ERR_NONE; 2238221229cb523f849f165fdafbf9785010963715daElliott Hughes } 2239221229cb523f849f165fdafbf9785010963715daElliott Hughes return error; 2240499c5133d361e7c659fc38e5ccfeb1280a7996f5Elliott Hughes } 2241499c5133d361e7c659fc38e5ccfeb1280a7996f5Elliott Hughes 22429e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes if (IsSuspendedForDebugger(soa, thread)) { 22439e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes *pSuspendStatus = JDWP::SUSPEND_STATUS_SUSPENDED; 22449e0c175a0cea5c8c88a6927e6375554118f74a82Elliott Hughes } 224500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 2246920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao *pThreadStatus = ToJdwpThreadStatus(thread->GetState()); 2247221229cb523f849f165fdafbf9785010963715daElliott Hughes return JDWP::ERR_NONE; 2248872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2249872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2250221229cb523f849f165fdafbf9785010963715daElliott HughesJDWP::JdwpError Dbg::GetThreadDebugSuspendCount(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply) { 225100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 2252c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 2253c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers Thread* thread = DecodeThread(soa, thread_id, &error); 2254221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error != JDWP::ERR_NONE) { 2255221229cb523f849f165fdafbf9785010963715daElliott Hughes return error; 22562435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 225750b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_); 225800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers expandBufAdd4BE(pReply, thread->GetDebugSuspendCount()); 22592435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes return JDWP::ERR_NONE; 2260872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2261872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2262f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott HughesJDWP::JdwpError Dbg::Interrupt(JDWP::ObjectId thread_id) { 2263f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes ScopedObjectAccess soa(Thread::Current()); 2264c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 2265c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers Thread* thread = DecodeThread(soa, thread_id, &error); 2266f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes if (error != JDWP::ERR_NONE) { 2267f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes return error; 2268f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes } 2269dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers thread->Interrupt(soa.Self()); 2270f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes return JDWP::ERR_NONE; 2271f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes} 2272f9501700f51586cb6ba7cc0ffcb5a920bd64adf1Elliott Hughes 227308883debd927d18c9ecf66683a2a11aa98165656Andreas Gampestatic bool IsInDesiredThreadGroup(mirror::Object* desired_thread_group, mirror::Object* peer) 2274bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 2275070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz // Do we want threads from all thread groups? 2276070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz if (desired_thread_group == nullptr) { 2277070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz return true; 2278070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz } 227908883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe ArtField* thread_group_field = jni::DecodeArtField(WellKnownClasses::java_lang_Thread_group); 2280070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz DCHECK(thread_group_field != nullptr); 22813398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier ObjPtr<mirror::Object> group = thread_group_field->GetObject(peer); 2282070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz return (group == desired_thread_group); 2283070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz} 2284a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 2285a06430c76981d545b5f2b64a7ef53c44c030cf73Sebastien Hertzvoid Dbg::GetThreads(mirror::Object* thread_group, std::vector<JDWP::ObjectId>* thread_ids) { 228600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 2287070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz std::list<Thread*> all_threads_list; 2288070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz { 2289070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz MutexLock mu(Thread::Current(), *Locks::thread_list_lock_); 2290070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz all_threads_list = Runtime::Current()->GetThreadList()->GetList(); 2291070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz } 2292070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz for (Thread* t : all_threads_list) { 2293070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz if (t == Dbg::GetDebugThread()) { 2294070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz // Skip the JDWP thread. Some debuggers get bent out of shape when they can't suspend and 2295070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz // query all threads, so it's easier if we just don't tell them about this thread. 2296070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz continue; 2297070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz } 2298070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz if (t->IsStillStarting()) { 2299070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz // This thread is being started (and has been registered in the thread list). However, it is 2300070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz // not completely started yet so we must ignore it. 2301070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz continue; 2302070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz } 2303cafa08146648442ee53348c4918a4fab29e591c1Nicolas Geoffray mirror::Object* peer = t->GetPeerFromOtherThread(); 2304070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz if (peer == nullptr) { 23052cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier // peer might be null if the thread is still starting up. We can't tell the debugger about 2306070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz // this thread yet. 2307070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz // TODO: if we identified threads to the debugger by their Thread* 2308070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz // rather than their peer's mirror::Object*, we could fix this. 2309070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz // Doing so might help us report ZOMBIE threads too. 2310070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz continue; 2311070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz } 231208883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe if (IsInDesiredThreadGroup(thread_group, peer)) { 2313070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz thread_ids->push_back(gRegistry->Add(peer)); 2314070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz } 2315070f732bc270f6b9a579838d3418eb13b9cdf8ffSebastien Hertz } 2316a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes} 2317a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 2318bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampestatic int GetStackDepth(Thread* thread) REQUIRES_SHARED(Locks::mutator_lock_) { 23190399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers struct CountStackDepthVisitor : public StackVisitor { 2320277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe explicit CountStackDepthVisitor(Thread* thread_in) 23218e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray : StackVisitor(thread_in, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), 23228e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray depth(0) {} 23230399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers 232464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses 232564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes // annotalysis. 232664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { 23270399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers if (!GetMethod()->IsRuntimeMethod()) { 2328f8a2df7bbf1021058bc13d1f806a7fec3c89ee62Elliott Hughes ++depth; 2329f8a2df7bbf1021058bc13d1f806a7fec3c89ee62Elliott Hughes } 2330530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return true; 2331a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes } 2332a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes size_t depth; 2333a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes }; 233408fc03ae5dded4adc9b45b7014a4b9dfedbe95a6Elliott Hughes 23357a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers CountStackDepthVisitor visitor(thread); 23360399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers visitor.WalkStack(); 2337a2e54f61453a2072181d5dd7aa2d5e845f5b53f6Elliott Hughes return visitor.depth; 2338872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2339872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2340c0542af3e2170143ba40d89136e284997e16bf64Ian RogersJDWP::JdwpError Dbg::GetThreadFrameCount(JDWP::ObjectId thread_id, size_t* result) { 234100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 2342c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 2343c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *result = 0; 2344c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers Thread* thread = DecodeThread(soa, thread_id, &error); 2345221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error != JDWP::ERR_NONE) { 2346221229cb523f849f165fdafbf9785010963715daElliott Hughes return error; 2347221229cb523f849f165fdafbf9785010963715daElliott Hughes } 2348f15f4a0136a7b797117355768851bc421b3afc93Elliott Hughes if (!IsSuspendedForDebugger(soa, thread)) { 2349f15f4a0136a7b797117355768851bc421b3afc93Elliott Hughes return JDWP::ERR_THREAD_NOT_SUSPENDED; 2350f15f4a0136a7b797117355768851bc421b3afc93Elliott Hughes } 2351c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers *result = GetStackDepth(thread); 2352221229cb523f849f165fdafbf9785010963715daElliott Hughes return JDWP::ERR_NONE; 23538696433d1b3d8ba15288483b777edd888de69135Elliott Hughes} 23548696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 2355306057fd278d75bf3794bd5243a3b6652c487d18Ian RogersJDWP::JdwpError Dbg::GetThreadFrames(JDWP::ObjectId thread_id, size_t start_frame, 2356306057fd278d75bf3794bd5243a3b6652c487d18Ian Rogers size_t frame_count, JDWP::ExpandBuf* buf) { 23576e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes class GetFrameVisitor : public StackVisitor { 23586e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes public: 2359277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe GetFrameVisitor(Thread* thread, size_t start_frame_in, size_t frame_count_in, 2360277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe JDWP::ExpandBuf* buf_in) 2361bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) 23628e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), 23638e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray depth_(0), 23648e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray start_frame_(start_frame_in), 23658e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray frame_count_(frame_count_in), 23668e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray buf_(buf_in) { 23676e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes expandBufAdd4BE(buf_, frame_count_); 236803181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes } 23690399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers 2370bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { 23710399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers if (GetMethod()->IsRuntimeMethod()) { 23727934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom return true; // The debugger can't do anything useful with a frame that has no Method*. 237303181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes } 23746e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes if (depth_ >= start_frame_ + frame_count_) { 2375530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return false; 237603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes } 23776e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes if (depth_ >= start_frame_) { 23786e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes JDWP::FrameId frame_id(GetFrameId()); 23796e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes JDWP::JdwpLocation location; 23806995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz SetJdwpLocation(&location, GetMethod(), GetDexPc()); 2381ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers VLOG(jdwp) << StringPrintf(" Frame %3zd: id=%3" PRIu64 " ", depth_, frame_id) << location; 23826e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes expandBufAdd8BE(buf_, frame_id); 23836e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes expandBufAddLocation(buf_, location); 23846e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes } 23856e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes ++depth_; 2386530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return true; 238703181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes } 23886e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes 23896e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes private: 23906e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes size_t depth_; 23916e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes const size_t start_frame_; 23926e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes const size_t frame_count_; 23936e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes JDWP::ExpandBuf* buf_; 239403181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes }; 239500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 239600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 2397c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 2398c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers Thread* thread = DecodeThread(soa, thread_id, &error); 2399221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error != JDWP::ERR_NONE) { 2400221229cb523f849f165fdafbf9785010963715daElliott Hughes return error; 2401221229cb523f849f165fdafbf9785010963715daElliott Hughes } 2402f15f4a0136a7b797117355768851bc421b3afc93Elliott Hughes if (!IsSuspendedForDebugger(soa, thread)) { 2403f15f4a0136a7b797117355768851bc421b3afc93Elliott Hughes return JDWP::ERR_THREAD_NOT_SUSPENDED; 2404f15f4a0136a7b797117355768851bc421b3afc93Elliott Hughes } 24057a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers GetFrameVisitor visitor(thread, start_frame, frame_count, buf); 24060399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers visitor.WalkStack(); 24076e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes return JDWP::ERR_NONE; 2408872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2409872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2410872d4ec7225444d9400d30f9027247deb91012fdElliott HughesJDWP::ObjectId Dbg::GetThreadSelfId() { 24116995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz return GetThreadId(Thread::Current()); 24126995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz} 24136995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz 24146995c60cd6657c10811055c42661a55b10b47cefSebastien HertzJDWP::ObjectId Dbg::GetThreadId(Thread* thread) { 2415dbe6f4613ae0161b169f4fca8a616b0b393370abMathieu Chartier ScopedObjectAccessUnchecked soa(Thread::Current()); 2416cafa08146648442ee53348c4918a4fab29e591c1Nicolas Geoffray return gRegistry->Add(thread->GetPeerFromOtherThread()); 2417872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2418872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2419475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughesvoid Dbg::SuspendVM() { 24208f95cf3cb5f715b1277de9cd7fade07ce4b230beHiroshi Yamauchi // Avoid a deadlock between GC and debugger where GC gets suspended during GC. b/25800335. 24218f95cf3cb5f715b1277de9cd7fade07ce4b230beHiroshi Yamauchi gc::ScopedGCCriticalSection gcs(Thread::Current(), 24228f95cf3cb5f715b1277de9cd7fade07ce4b230beHiroshi Yamauchi gc::kGcCauseDebugger, 24238f95cf3cb5f715b1277de9cd7fade07ce4b230beHiroshi Yamauchi gc::kCollectorTypeDebugger); 242400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers Runtime::Current()->GetThreadList()->SuspendAllForDebugger(); 2425872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2426872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2427872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::ResumeVM() { 2428253fa555d9424a56c52879449eabe73d5c96cf61Sebastien Hertz Runtime::Current()->GetThreadList()->ResumeAllForDebugger(); 2429872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2430872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2431221229cb523f849f165fdafbf9785010963715daElliott HughesJDWP::JdwpError Dbg::SuspendThread(JDWP::ObjectId thread_id, bool request_suspension) { 2432f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers Thread* self = Thread::Current(); 2433c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers ScopedLocalRef<jobject> peer(self->GetJniEnv(), nullptr); 243400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers { 2435f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers ScopedObjectAccess soa(self); 2436c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 2437c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers peer.reset(soa.AddLocalReference<jobject>(gRegistry->Get<mirror::Object*>(thread_id, &error))); 243800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 2439c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (peer.get() == nullptr) { 244000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return JDWP::ERR_THREAD_NOT_ALIVE; 244100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 24424ad5cd3e7d519484559ef778d96fb3f0be8919faIan Rogers // Suspend thread to build stack trace. 2443f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes bool timed_out; 2444ba32de47e32f436d7c11cb4a2e78bdd4ad4dc5d2Brian Carlstrom ThreadList* thread_list = Runtime::Current()->GetThreadList(); 2445cdd798de1b2e7807f1cab8ebbfbb165069beae6bSebastien Hertz Thread* thread = thread_list->SuspendThreadByPeer(peer.get(), 2446cdd798de1b2e7807f1cab8ebbfbb165069beae6bSebastien Hertz request_suspension, 2447cdd798de1b2e7807f1cab8ebbfbb165069beae6bSebastien Hertz /* debug_suspension */ true, 2448ba32de47e32f436d7c11cb4a2e78bdd4ad4dc5d2Brian Carlstrom &timed_out); 2449c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (thread != nullptr) { 245000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return JDWP::ERR_NONE; 2451f327e07b37e349b1ec5eaad6dc294a9b7a081d20Elliott Hughes } else if (timed_out) { 245200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return JDWP::ERR_INTERNAL; 245300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else { 245400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return JDWP::ERR_THREAD_NOT_ALIVE; 24554e235316b4ada4d865c544d9b4ba397139333fa6Elliott Hughes } 2456872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2457872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2458221229cb523f849f165fdafbf9785010963715daElliott Hughesvoid Dbg::ResumeThread(JDWP::ObjectId thread_id) { 245900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 2460c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 2461c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Object* peer = gRegistry->Get<mirror::Object*>(thread_id, &error); 2462c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers CHECK(peer != nullptr) << error; 2463a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao Thread* thread; 2464a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao { 2465a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao MutexLock mu(soa.Self(), *Locks::thread_list_lock_); 2466a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao thread = Thread::FromManagedThread(soa, peer); 2467a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao } 2468c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (thread == nullptr) { 24694e235316b4ada4d865c544d9b4ba397139333fa6Elliott Hughes LOG(WARNING) << "No such thread for resume: " << peer; 24704e235316b4ada4d865c544d9b4ba397139333fa6Elliott Hughes return; 24714e235316b4ada4d865c544d9b4ba397139333fa6Elliott Hughes } 247200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool needs_resume; 247300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers { 247450b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_); 247570d60275cc2860bde50e5f9c5b151e94f745ae14Sebastien Hertz needs_resume = thread->GetDebugSuspendCount() > 0; 247600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 247700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (needs_resume) { 2478546b986ecd09c2a498740bd8bf7127e612d94755Elliott Hughes Runtime::Current()->GetThreadList()->Resume(thread, true); 2479546b986ecd09c2a498740bd8bf7127e612d94755Elliott Hughes } 2480872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2481872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2482872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::SuspendSelf() { 2483475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes Runtime::Current()->GetThreadList()->SuspendSelfForDebugger(); 2484872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2485872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 24860399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogersstruct GetThisVisitor : public StackVisitor { 2487277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe GetThisVisitor(Thread* thread, Context* context, JDWP::FrameId frame_id_in) 2488bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) 24898e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames), 24908e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray this_object(nullptr), 24918e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray frame_id(frame_id_in) {} 249268fdbd07fc2b8856905e06f3cc945b046c3bfcd3Elliott Hughes 249300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses 249400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // annotalysis. 249500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers virtual bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { 24966e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes if (frame_id != GetFrameId()) { 24970399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers return true; // continue 24980399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } else { 249962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers this_object = GetThisObject(); 250062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return false; 25010399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 250268fdbd07fc2b8856905e06f3cc945b046c3bfcd3Elliott Hughes } 2503dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes 25042dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* this_object; 25056e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes JDWP::FrameId frame_id; 25060399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers}; 2507ad3da694bbba88662d1d1bd2cc574d6e3ab6cd42Elliott Hughes 250800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan RogersJDWP::JdwpError Dbg::GetThisObject(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, 250900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JDWP::ObjectId* result) { 251000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 2511692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz JDWP::JdwpError error; 2512692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz Thread* thread = DecodeThread(soa, thread_id, &error); 2513692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz if (error != JDWP::ERR_NONE) { 2514692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz return error; 2515692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz } 2516692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz if (!IsSuspendedForDebugger(soa, thread)) { 2517692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz return JDWP::ERR_THREAD_NOT_SUSPENDED; 25186e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes } 2519700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<Context> context(Context::Create()); 25207a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers GetThisVisitor visitor(thread, context.get(), frame_id); 25210399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers visitor.WalkStack(); 25226e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes *result = gRegistry->Add(visitor.this_object); 25236e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes return JDWP::ERR_NONE; 25240399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers} 25250399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers 25268009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz// Walks the stack until we find the frame with the given FrameId. 25278009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertzclass FindFrameVisitor FINAL : public StackVisitor { 25288009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz public: 25298009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz FindFrameVisitor(Thread* thread, Context* context, JDWP::FrameId frame_id) 2530bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) 25318e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames), 25328e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray frame_id_(frame_id), 25338e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray error_(JDWP::ERR_INVALID_FRAMEID) {} 2534ad3da694bbba88662d1d1bd2cc574d6e3ab6cd42Elliott Hughes 25358009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses 25368009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz // annotalysis. 25378009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { 25388009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz if (GetFrameId() != frame_id_) { 25398009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz return true; // Not our frame, carry on. 25400399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 2541e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m = GetMethod(); 25428009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz if (m->IsNative()) { 25438009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz // We can't read/write local value from/into native method. 25448009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz error_ = JDWP::ERR_OPAQUE_FRAME; 25458009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } else { 25468009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz // We found our frame. 25478009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz error_ = JDWP::ERR_NONE; 25488009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 25498009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz return false; 25508009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 25518009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz 25528009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz JDWP::JdwpError GetError() const { 25538009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz return error_; 25548009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 25558009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz 25568009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz private: 25578009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz const JDWP::FrameId frame_id_; 25588009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz JDWP::JdwpError error_; 255926f728661a08062a373a3203b72dc2555c2aed2dSebastien Hertz 256026f728661a08062a373a3203b72dc2555c2aed2dSebastien Hertz DISALLOW_COPY_AND_ASSIGN(FindFrameVisitor); 25618009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz}; 25628009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz 25638009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien HertzJDWP::JdwpError Dbg::GetLocalValues(JDWP::Request* request, JDWP::ExpandBuf* pReply) { 25648009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz JDWP::ObjectId thread_id = request->ReadThreadId(); 25658009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz JDWP::FrameId frame_id = request->ReadFrameId(); 256600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 256700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 2568692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz JDWP::JdwpError error; 2569692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz Thread* thread = DecodeThread(soa, thread_id, &error); 2570692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz if (error != JDWP::ERR_NONE) { 2571692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz return error; 2572692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz } 2573692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz if (!IsSuspendedForDebugger(soa, thread)) { 2574692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz return JDWP::ERR_THREAD_NOT_SUSPENDED; 2575221229cb523f849f165fdafbf9785010963715daElliott Hughes } 25768009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz // Find the frame with the given frame_id. 2577700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<Context> context(Context::Create()); 25788009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz FindFrameVisitor visitor(thread, context.get(), frame_id); 25790399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers visitor.WalkStack(); 25808009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz if (visitor.GetError() != JDWP::ERR_NONE) { 25818009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz return visitor.GetError(); 25828009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 25830399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers 25848009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz // Read the values from visitor's context. 25858009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz int32_t slot_count = request->ReadSigned32("slot count"); 25868009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz expandBufAdd4BE(pReply, slot_count); /* "int values" */ 25878009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz for (int32_t i = 0; i < slot_count; ++i) { 25888009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz uint32_t slot = request->ReadUnsigned32("slot"); 25898009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz JDWP::JdwpTag reqSigByte = request->ReadTag(); 2590ca190666fb11820153f74274c495ba1f913d8a69Ian Rogers 25918009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz VLOG(jdwp) << " --> slot " << slot << " " << reqSigByte; 25928009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz 25938009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz size_t width = Dbg::GetTagWidth(reqSigByte); 25947d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz uint8_t* ptr = expandBufAddSpace(pReply, width + 1); 2595692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz error = Dbg::GetLocalValue(visitor, soa, slot, reqSigByte, ptr, width); 25968009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz if (error != JDWP::ERR_NONE) { 25978009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz return error; 25988009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 25998009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 26008009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz return JDWP::ERR_NONE; 26018009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz} 26028009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz 2603abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertzconstexpr JDWP::JdwpError kStackFrameLocalAccessError = JDWP::ERR_ABSENT_INFORMATION; 2604abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz 2605abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertzstatic std::string GetStackContextAsString(const StackVisitor& visitor) 2606bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 2607abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return StringPrintf(" at DEX pc 0x%08x in method %s", visitor.GetDexPc(false), 2608709b070044354d9f47641f273edacaeeb0240ab7David Sehr ArtMethod::PrettyMethod(visitor.GetMethod()).c_str()); 2609abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz} 2610abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz 2611abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertzstatic JDWP::JdwpError FailGetLocalValue(const StackVisitor& visitor, uint16_t vreg, 2612abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz JDWP::JdwpTag tag) 2613bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 2614abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz LOG(ERROR) << "Failed to read " << tag << " local from register v" << vreg 2615abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz << GetStackContextAsString(visitor); 2616abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return kStackFrameLocalAccessError; 2617abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz} 2618abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz 26198009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien HertzJDWP::JdwpError Dbg::GetLocalValue(const StackVisitor& visitor, ScopedObjectAccessUnchecked& soa, 26208009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz int slot, JDWP::JdwpTag tag, uint8_t* buf, size_t width) { 2621e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m = visitor.GetMethod(); 2622abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz JDWP::JdwpError error = JDWP::ERR_NONE; 2623abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz uint16_t vreg = DemangleSlot(slot, m, &error); 2624abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz if (error != JDWP::ERR_NONE) { 2625abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return error; 2626abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz } 26278009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz // TODO: check that the tag is compatible with the actual type of the slot! 26288009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz switch (tag) { 26298009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_BOOLEAN: { 26308009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz CHECK_EQ(width, 1U); 26318009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz uint32_t intVal; 2632abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz if (!visitor.GetVReg(m, vreg, kIntVReg, &intVal)) { 2633abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return FailGetLocalValue(visitor, vreg, tag); 2634ad3da694bbba88662d1d1bd2cc574d6e3ab6cd42Elliott Hughes } 2635abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz VLOG(jdwp) << "get boolean local " << vreg << " = " << intVal; 2636abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz JDWP::Set1(buf + 1, intVal != 0); 26378009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz break; 26388009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 26398009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_BYTE: { 26408009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz CHECK_EQ(width, 1U); 26418009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz uint32_t intVal; 2642abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz if (!visitor.GetVReg(m, vreg, kIntVReg, &intVal)) { 2643abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return FailGetLocalValue(visitor, vreg, tag); 2644cb19ebf7609f74b223bd86c94f721498795f9bbaSebastien Hertz } 2645abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz VLOG(jdwp) << "get byte local " << vreg << " = " << intVal; 2646abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz JDWP::Set1(buf + 1, intVal); 26478009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz break; 26488009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 26498009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_SHORT: 26508009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_CHAR: { 26518009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz CHECK_EQ(width, 2U); 26528009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz uint32_t intVal; 2653abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz if (!visitor.GetVReg(m, vreg, kIntVReg, &intVal)) { 2654abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return FailGetLocalValue(visitor, vreg, tag); 26558009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 2656abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz VLOG(jdwp) << "get short/char local " << vreg << " = " << intVal; 2657abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz JDWP::Set2BE(buf + 1, intVal); 26588009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz break; 26598009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 26608009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_INT: { 26618009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz CHECK_EQ(width, 4U); 26628009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz uint32_t intVal; 2663abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz if (!visitor.GetVReg(m, vreg, kIntVReg, &intVal)) { 2664abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return FailGetLocalValue(visitor, vreg, tag); 26658009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 2666abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz VLOG(jdwp) << "get int local " << vreg << " = " << intVal; 2667abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz JDWP::Set4BE(buf + 1, intVal); 26688009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz break; 26698009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 26708009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_FLOAT: { 26718009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz CHECK_EQ(width, 4U); 26728009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz uint32_t intVal; 2673abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz if (!visitor.GetVReg(m, vreg, kFloatVReg, &intVal)) { 2674abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return FailGetLocalValue(visitor, vreg, tag); 26758009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 2676abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz VLOG(jdwp) << "get float local " << vreg << " = " << intVal; 2677abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz JDWP::Set4BE(buf + 1, intVal); 26788009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz break; 26798009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 26808009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_ARRAY: 26818009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_CLASS_LOADER: 26828009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_CLASS_OBJECT: 26838009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_OBJECT: 26848009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_STRING: 26858009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_THREAD: 26868009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_THREAD_GROUP: { 26878009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz CHECK_EQ(width, sizeof(JDWP::ObjectId)); 26888009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz uint32_t intVal; 2689abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz if (!visitor.GetVReg(m, vreg, kReferenceVReg, &intVal)) { 2690abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return FailGetLocalValue(visitor, vreg, tag); 2691abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz } 2692abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz mirror::Object* o = reinterpret_cast<mirror::Object*>(intVal); 2693abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz VLOG(jdwp) << "get " << tag << " object local " << vreg << " = " << o; 2694abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) { 2695abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz LOG(FATAL) << StringPrintf("Found invalid object %#" PRIxPTR " in register v%u", 2696abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz reinterpret_cast<uintptr_t>(o), vreg) 2697abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz << GetStackContextAsString(visitor); 2698abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz UNREACHABLE(); 26990399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers } 2700abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz tag = TagFromObject(soa, o); 2701abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz JDWP::SetObjectId(buf + 1, gRegistry->Add(o)); 27028009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz break; 27038009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 27048009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_DOUBLE: { 27058009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz CHECK_EQ(width, 8U); 27068009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz uint64_t longVal; 2707abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz if (!visitor.GetVRegPair(m, vreg, kDoubleLoVReg, kDoubleHiVReg, &longVal)) { 2708abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return FailGetLocalValue(visitor, vreg, tag); 27098009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 2710abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz VLOG(jdwp) << "get double local " << vreg << " = " << longVal; 2711abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz JDWP::Set8BE(buf + 1, longVal); 27128009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz break; 27138009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 27148009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_LONG: { 27158009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz CHECK_EQ(width, 8U); 27168009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz uint64_t longVal; 2717abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz if (!visitor.GetVRegPair(m, vreg, kLongLoVReg, kLongHiVReg, &longVal)) { 2718abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return FailGetLocalValue(visitor, vreg, tag); 27198009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 2720abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz VLOG(jdwp) << "get long local " << vreg << " = " << longVal; 2721abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz JDWP::Set8BE(buf + 1, longVal); 27228009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz break; 2723cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes } 27248009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz default: 27258009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz LOG(FATAL) << "Unknown tag " << tag; 2726abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz UNREACHABLE(); 27278009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 27280399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers 27298009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz // Prepend tag, which may have been updated. 27308009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz JDWP::Set1(buf, tag); 27318009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz return JDWP::ERR_NONE; 27328009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz} 27338009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz 27348009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien HertzJDWP::JdwpError Dbg::SetLocalValues(JDWP::Request* request) { 27358009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz JDWP::ObjectId thread_id = request->ReadThreadId(); 27368009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz JDWP::FrameId frame_id = request->ReadFrameId(); 273700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 273800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 2739692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz JDWP::JdwpError error; 2740692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz Thread* thread = DecodeThread(soa, thread_id, &error); 2741692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz if (error != JDWP::ERR_NONE) { 2742692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz return error; 2743692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz } 2744692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz if (!IsSuspendedForDebugger(soa, thread)) { 2745692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz return JDWP::ERR_THREAD_NOT_SUSPENDED; 2746221229cb523f849f165fdafbf9785010963715daElliott Hughes } 27478009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz // Find the frame with the given frame_id. 2748700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<Context> context(Context::Create()); 27498009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz FindFrameVisitor visitor(thread, context.get(), frame_id); 27500399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers visitor.WalkStack(); 27518009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz if (visitor.GetError() != JDWP::ERR_NONE) { 27528009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz return visitor.GetError(); 27538009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 27548009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz 27558009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz // Writes the values into visitor's context. 27568009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz int32_t slot_count = request->ReadSigned32("slot count"); 27578009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz for (int32_t i = 0; i < slot_count; ++i) { 27588009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz uint32_t slot = request->ReadUnsigned32("slot"); 27598009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz JDWP::JdwpTag sigByte = request->ReadTag(); 27608009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz size_t width = Dbg::GetTagWidth(sigByte); 27618009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz uint64_t value = request->ReadValue(width); 27628009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz 27638009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz VLOG(jdwp) << " --> slot " << slot << " " << sigByte << " " << value; 276499170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang error = Dbg::SetLocalValue(thread, visitor, slot, sigByte, value, width); 27658009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz if (error != JDWP::ERR_NONE) { 27668009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz return error; 27678009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 27688009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 27698009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz return JDWP::ERR_NONE; 27708009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz} 27718009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz 2772abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertztemplate<typename T> 2773abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertzstatic JDWP::JdwpError FailSetLocalValue(const StackVisitor& visitor, uint16_t vreg, 2774abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz JDWP::JdwpTag tag, T value) 2775bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 2776abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz LOG(ERROR) << "Failed to write " << tag << " local " << value 2777abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz << " (0x" << std::hex << value << ") into register v" << vreg 2778abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz << GetStackContextAsString(visitor); 2779abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return kStackFrameLocalAccessError; 2780abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz} 2781abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz 278299170c636dfae4908b102347cfe9f92bad1881ccMingyao YangJDWP::JdwpError Dbg::SetLocalValue(Thread* thread, StackVisitor& visitor, int slot, 278399170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang JDWP::JdwpTag tag, uint64_t value, size_t width) { 2784e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m = visitor.GetMethod(); 2785abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz JDWP::JdwpError error = JDWP::ERR_NONE; 2786abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz uint16_t vreg = DemangleSlot(slot, m, &error); 2787abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz if (error != JDWP::ERR_NONE) { 2788abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return error; 2789abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz } 27908009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz // TODO: check that the tag is compatible with the actual type of the slot! 27918009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz switch (tag) { 27928009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_BOOLEAN: 27938009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_BYTE: 27948009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz CHECK_EQ(width, 1U); 2795636b9252af8d8848dbf8f30b7e9638867b62c791Mingyao Yang if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(value), kIntVReg)) { 2796abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return FailSetLocalValue(visitor, vreg, tag, static_cast<uint32_t>(value)); 27978009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 27988009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz break; 27998009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_SHORT: 28008009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_CHAR: 28018009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz CHECK_EQ(width, 2U); 2802636b9252af8d8848dbf8f30b7e9638867b62c791Mingyao Yang if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(value), kIntVReg)) { 2803abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return FailSetLocalValue(visitor, vreg, tag, static_cast<uint32_t>(value)); 28048009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 28058009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz break; 28068009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_INT: 28078009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz CHECK_EQ(width, 4U); 2808636b9252af8d8848dbf8f30b7e9638867b62c791Mingyao Yang if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(value), kIntVReg)) { 2809abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return FailSetLocalValue(visitor, vreg, tag, static_cast<uint32_t>(value)); 28108009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 28118009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz break; 28128009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_FLOAT: 28138009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz CHECK_EQ(width, 4U); 2814636b9252af8d8848dbf8f30b7e9638867b62c791Mingyao Yang if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(value), kFloatVReg)) { 2815abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return FailSetLocalValue(visitor, vreg, tag, static_cast<uint32_t>(value)); 28168009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 28178009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz break; 28188009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_ARRAY: 28198009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_CLASS_LOADER: 28208009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_CLASS_OBJECT: 28218009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_OBJECT: 28228009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_STRING: 28238009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_THREAD: 28248009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_THREAD_GROUP: { 28258009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz CHECK_EQ(width, sizeof(JDWP::ObjectId)); 28268009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz mirror::Object* o = gRegistry->Get<mirror::Object*>(static_cast<JDWP::ObjectId>(value), 28278009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz &error); 28288009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz if (error != JDWP::ERR_NONE) { 28298009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz VLOG(jdwp) << tag << " object " << o << " is an invalid object"; 28308009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz return JDWP::ERR_INVALID_OBJECT; 2831abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz } 2832636b9252af8d8848dbf8f30b7e9638867b62c791Mingyao Yang if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(o)), 2833abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz kReferenceVReg)) { 2834abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return FailSetLocalValue(visitor, vreg, tag, reinterpret_cast<uintptr_t>(o)); 28358009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 28368009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz break; 28378009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 28388009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_DOUBLE: { 28398009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz CHECK_EQ(width, 8U); 2840636b9252af8d8848dbf8f30b7e9638867b62c791Mingyao Yang if (!visitor.SetVRegPair(m, vreg, value, kDoubleLoVReg, kDoubleHiVReg)) { 2841abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return FailSetLocalValue(visitor, vreg, tag, value); 28428009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 28438009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz break; 28448009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 28458009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz case JDWP::JT_LONG: { 28468009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz CHECK_EQ(width, 8U); 2847636b9252af8d8848dbf8f30b7e9638867b62c791Mingyao Yang if (!visitor.SetVRegPair(m, vreg, value, kLongLoVReg, kLongHiVReg)) { 2848abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz return FailSetLocalValue(visitor, vreg, tag, value); 28498009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 28508009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz break; 28518009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 28528009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz default: 28538009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz LOG(FATAL) << "Unknown tag " << tag; 2854abbabc8acca2231edc5d6e95d523e3fde9a0ba9fSebastien Hertz UNREACHABLE(); 28558009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz } 285699170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang 285799170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang // If we set the local variable in a compiled frame, we need to trigger a deoptimization of 285899170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang // the stack so we continue execution with the interpreter using the new value(s) of the updated 285999170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang // local variable(s). To achieve this, we install instrumentation exit stub on each method of the 286099170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang // thread's stack. The stub will cause the deoptimization to happen. 286199170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang if (!visitor.IsShadowFrame() && thread->HasDebuggerShadowFrames()) { 286299170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang Runtime::Current()->GetInstrumentation()->InstrumentThreadStack(thread); 286399170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang } 286499170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang 28658009f39c6d63181a6cd0e348ce732997dbdf3d20Sebastien Hertz return JDWP::ERR_NONE; 2866872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2867872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2868e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic void SetEventLocation(JDWP::EventLocation* location, ArtMethod* m, uint32_t dex_pc) 2869bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 28706995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz DCHECK(location != nullptr); 28716995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz if (m == nullptr) { 28726995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz memset(location, 0, sizeof(*location)); 28736995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz } else { 28746c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light location->method = GetCanonicalMethod(m); 28756995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz location->dex_pc = (m->IsNative() || m->IsProxyMethod()) ? static_cast<uint32_t>(-1) : dex_pc; 28763f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz } 28773f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz} 28783f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz 2879e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid Dbg::PostLocationEvent(ArtMethod* m, int dex_pc, mirror::Object* this_object, 2880579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao int event_flags, const JValue* return_value) { 28813f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz if (!IsDebuggerActive()) { 28823f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz return; 28833f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz } 28843f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz DCHECK(m != nullptr); 28853f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz DCHECK_EQ(m->IsStatic(), this_object == nullptr); 28866995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz JDWP::EventLocation location; 28876995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz SetEventLocation(&location, m, dex_pc); 288891bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes 2889de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz // We need to be sure no exception is pending when calling JdwpState::PostLocationEvent. 2890de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz // This is required to be able to call JNI functions to create JDWP ids. To achieve this, 2891de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz // we temporarily clear the current thread's exception (if any) and will restore it after 2892de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz // the call. 2893de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz // Note: the only way to get a pending exception here is to suspend on a move-exception 2894de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz // instruction. 2895de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz Thread* const self = Thread::Current(); 2896de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz StackHandleScope<1> hs(self); 2897de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz Handle<mirror::Throwable> pending_exception(hs.NewHandle(self->GetException())); 2898de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz self->ClearException(); 2899fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe if (kIsDebugBuild && pending_exception != nullptr) { 2900de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz const DexFile::CodeItem* code_item = location.method->GetCodeItem(); 2901de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz const Instruction* instr = Instruction::At(&code_item->insns_[location.dex_pc]); 2902de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz CHECK_EQ(Instruction::MOVE_EXCEPTION, instr->Opcode()); 2903de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz } 2904de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz 29056995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz gJdwpState->PostLocationEvent(&location, this_object, event_flags, return_value); 2906de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz 2907fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe if (pending_exception != nullptr) { 2908de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz self->SetException(pending_exception.Get()); 2909de48aa6708a3d5dacf7db3d64965e23261fb15d3Sebastien Hertz } 2910872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 2911872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 2912e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid Dbg::PostFieldAccessEvent(ArtMethod* m, int dex_pc, 2913c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier mirror::Object* this_object, ArtField* f) { 29143f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz if (!IsDebuggerActive()) { 29153f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz return; 29163f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz } 29173f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz DCHECK(m != nullptr); 29183f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz DCHECK(f != nullptr); 29196995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz JDWP::EventLocation location; 29206995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz SetEventLocation(&location, m, dex_pc); 29213f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz 29226995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz gJdwpState->PostFieldEvent(&location, f, this_object, nullptr, false); 29233f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz} 29243f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz 2925e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid Dbg::PostFieldModificationEvent(ArtMethod* m, int dex_pc, 2926c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier mirror::Object* this_object, ArtField* f, 29273f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz const JValue* field_value) { 29283f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz if (!IsDebuggerActive()) { 29293f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz return; 29303f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz } 29313f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz DCHECK(m != nullptr); 29323f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz DCHECK(f != nullptr); 29333f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz DCHECK(field_value != nullptr); 29346995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz JDWP::EventLocation location; 29356995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz SetEventLocation(&location, m, dex_pc); 29363f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz 29376995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz gJdwpState->PostFieldEvent(&location, f, this_object, field_value, true); 29383f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz} 29393f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz 294014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray/** 294114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray * Finds the location where this exception will be caught. We search until we reach the top 294214691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray * frame, in which case this exception is considered uncaught. 294314691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray */ 294414691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffrayclass CatchLocationFinder : public StackVisitor { 294514691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray public: 294614691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray CatchLocationFinder(Thread* self, const Handle<mirror::Throwable>& exception, Context* context) 2947bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) 29488e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray : StackVisitor(self, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames), 294914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray exception_(exception), 295014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray handle_scope_(self), 295114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray this_at_throw_(handle_scope_.NewHandle<mirror::Object>(nullptr)), 2952e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier catch_method_(nullptr), 2953e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier throw_method_(nullptr), 295414691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray catch_dex_pc_(DexFile::kDexNoIndex), 295514691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray throw_dex_pc_(DexFile::kDexNoIndex) { 295614691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray } 295714691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray 2958bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { 2959e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* method = GetMethod(); 296014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray DCHECK(method != nullptr); 296114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray if (method->IsRuntimeMethod()) { 296214691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray // Ignore callee save method. 296314691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray DCHECK(method->IsCalleeSaveMethod()); 296414691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray return true; 296514691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray } 296614691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray 296714691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray uint32_t dex_pc = GetDexPc(); 2968e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier if (throw_method_ == nullptr) { 296914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray // First Java method found. It is either the method that threw the exception, 297014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray // or the Java native method that is reporting an exception thrown by 297114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray // native code. 297214691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray this_at_throw_.Assign(GetThisObject()); 2973e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier throw_method_ = method; 297414691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray throw_dex_pc_ = dex_pc; 297514691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray } 297614691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray 297714691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray if (dex_pc != DexFile::kDexNoIndex) { 297826f728661a08062a373a3203b72dc2555c2aed2dSebastien Hertz StackHandleScope<1> hs(GetThread()); 297914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray uint32_t found_dex_pc; 298014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray Handle<mirror::Class> exception_class(hs.NewHandle(exception_->GetClass())); 298114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray bool unused_clear_exception; 2982e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier found_dex_pc = method->FindCatchBlock(exception_class, dex_pc, &unused_clear_exception); 298314691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray if (found_dex_pc != DexFile::kDexNoIndex) { 2984e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier catch_method_ = method; 298514691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray catch_dex_pc_ = found_dex_pc; 298614691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray return false; // End stack walk. 298714691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray } 298814691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray } 298914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray return true; // Continue stack walk. 299014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray } 299114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray 2992bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe ArtMethod* GetCatchMethod() REQUIRES_SHARED(Locks::mutator_lock_) { 2993e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier return catch_method_; 299414691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray } 299514691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray 2996bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe ArtMethod* GetThrowMethod() REQUIRES_SHARED(Locks::mutator_lock_) { 2997e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier return throw_method_; 299814691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray } 299914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray 3000bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe mirror::Object* GetThisAtThrow() REQUIRES_SHARED(Locks::mutator_lock_) { 300114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray return this_at_throw_.Get(); 300214691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray } 300314691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray 300414691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray uint32_t GetCatchDexPc() const { 300514691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray return catch_dex_pc_; 300614691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray } 300714691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray 300814691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray uint32_t GetThrowDexPc() const { 300914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray return throw_dex_pc_; 301014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray } 301114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray 301214691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray private: 301314691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray const Handle<mirror::Throwable>& exception_; 3014e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier StackHandleScope<1> handle_scope_; 301514691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray MutableHandle<mirror::Object> this_at_throw_; 3016e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* catch_method_; 3017e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* throw_method_; 301814691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray uint32_t catch_dex_pc_; 301914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray uint32_t throw_dex_pc_; 302014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray 302114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray DISALLOW_COPY_AND_ASSIGN(CatchLocationFinder); 302214691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray}; 302314691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray 302414691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffrayvoid Dbg::PostException(mirror::Throwable* exception_object) { 3025c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes if (!IsDebuggerActive()) { 30260ad5bb8ea378a223eb6eaf89e0be2823c6f87c0eIan Rogers return; 30270ad5bb8ea378a223eb6eaf89e0be2823c6f87c0eIan Rogers } 3028261bc044a3575512869586593e99e97cd8b1c321Sebastien Hertz Thread* const self = Thread::Current(); 3029261bc044a3575512869586593e99e97cd8b1c321Sebastien Hertz StackHandleScope<1> handle_scope(self); 303014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray Handle<mirror::Throwable> h_exception(handle_scope.NewHandle(exception_object)); 303114691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray std::unique_ptr<Context> context(Context::Create()); 3032261bc044a3575512869586593e99e97cd8b1c321Sebastien Hertz CatchLocationFinder clf(self, h_exception, context.get()); 303314691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray clf.WalkStack(/* include_transitions */ false); 30346995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz JDWP::EventLocation exception_throw_location; 303514691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray SetEventLocation(&exception_throw_location, clf.GetThrowMethod(), clf.GetThrowDexPc()); 30366995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz JDWP::EventLocation exception_catch_location; 303714691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray SetEventLocation(&exception_catch_location, clf.GetCatchMethod(), clf.GetCatchDexPc()); 30384740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes 303914691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray gJdwpState->PostException(&exception_throw_location, h_exception.Get(), &exception_catch_location, 304014691c5e786e8c2c5734f687e4c96217340771beNicolas Geoffray clf.GetThisAtThrow()); 3041872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 3042872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 30432dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersvoid Dbg::PostClassPrepare(mirror::Class* c) { 3044c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes if (!IsDebuggerActive()) { 30454740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes return; 30464740cdff25875c530649a670b15e8ac52bfd7252Elliott Hughes } 30476995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz gJdwpState->PostClassPrepare(c); 3048872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 3049872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 305062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Dbg::UpdateDebugger(Thread* thread, mirror::Object* this_object, 3051e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m, uint32_t dex_pc, 30528379b2256be5d2be4ad083a76e9f8ec403c4d405Sebastien Hertz int event_flags, const JValue* return_value) { 305362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (!IsDebuggerActive() || dex_pc == static_cast<uint32_t>(-2) /* fake method exit */) { 30542aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes return; 305591bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes } 305691bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes 30578696433d1b3d8ba15288483b777edd888de69135Elliott Hughes if (IsBreakpoint(m, dex_pc)) { 30588696433d1b3d8ba15288483b777edd888de69135Elliott Hughes event_flags |= kBreakpoint; 305991bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes } 306091bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes 306161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // If the debugger is single-stepping one of our threads, check to 306261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // see if we're that thread and we've reached a step point. 306361b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz const SingleStepControl* single_step_control = thread->GetSingleStepControl(); 3064597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz if (single_step_control != nullptr) { 306561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz CHECK(!m->IsNative()); 3066597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz if (single_step_control->GetStepDepth() == JDWP::SD_INTO) { 306761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // Step into method calls. We break when the line number 306861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // or method pointer changes. If we're in SS_MIN mode, we 306961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // always stop. 3070597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz if (single_step_control->GetMethod() != m) { 307161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz event_flags |= kSingleStep; 307261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz VLOG(jdwp) << "SS new method"; 3073597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz } else if (single_step_control->GetStepSize() == JDWP::SS_MIN) { 307461b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz event_flags |= kSingleStep; 307561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz VLOG(jdwp) << "SS new instruction"; 3076bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz } else if (single_step_control->ContainsDexPc(dex_pc)) { 307761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz event_flags |= kSingleStep; 307861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz VLOG(jdwp) << "SS new line"; 307961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz } 3080597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz } else if (single_step_control->GetStepDepth() == JDWP::SD_OVER) { 308161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // Step over method calls. We break when the line number is 308261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // different and the frame depth is <= the original frame 308361b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // depth. (We can't just compare on the method, because we 308461b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // might get unrolled past it by an exception, and it's tricky 308561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // to identify recursion.) 308661b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz 308761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz int stack_depth = GetStackDepth(thread); 308861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz 3089597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz if (stack_depth < single_step_control->GetStackDepth()) { 309061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // Popped up one or more frames, always trigger. 309161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz event_flags |= kSingleStep; 309261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz VLOG(jdwp) << "SS method pop"; 3093597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz } else if (stack_depth == single_step_control->GetStackDepth()) { 309461b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // Same depth, see if we moved. 3095597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz if (single_step_control->GetStepSize() == JDWP::SS_MIN) { 30968696433d1b3d8ba15288483b777edd888de69135Elliott Hughes event_flags |= kSingleStep; 30978696433d1b3d8ba15288483b777edd888de69135Elliott Hughes VLOG(jdwp) << "SS new instruction"; 3098bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz } else if (single_step_control->ContainsDexPc(dex_pc)) { 30992435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes event_flags |= kSingleStep; 31002435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes VLOG(jdwp) << "SS new line"; 310191bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes } 310261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz } 310361b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz } else { 3104597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz CHECK_EQ(single_step_control->GetStepDepth(), JDWP::SD_OUT); 310561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // Return from the current method. We break when the frame 310661b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // depth pops up. 310761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz 310861b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // This differs from the "method exit" break in that it stops 310961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // with the PC at the next instruction in the returned-to 311061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz // function, rather than the end of the returning function. 311161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz 311261b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz int stack_depth = GetStackDepth(thread); 3113597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz if (stack_depth < single_step_control->GetStackDepth()) { 311461b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz event_flags |= kSingleStep; 311561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz VLOG(jdwp) << "SS method pop"; 31168696433d1b3d8ba15288483b777edd888de69135Elliott Hughes } 311791bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes } 311891bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes } 311991bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes 312091bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes // If there's something interesting going on, see if it matches one 312191bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes // of the debugger filters. 312291bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes if (event_flags != 0) { 31238379b2256be5d2be4ad083a76e9f8ec403c4d405Sebastien Hertz Dbg::PostLocationEvent(m, dex_pc, this_object, event_flags, return_value); 312491bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes } 312591bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes} 312691bf6cd47174f5c17265320f7a350722720390a5Elliott Hughes 312742cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertzsize_t* Dbg::GetReferenceCounterForEvent(uint32_t instrumentation_event) { 312842cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz switch (instrumentation_event) { 312942cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz case instrumentation::Instrumentation::kMethodEntered: 313042cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz return &method_enter_event_ref_count_; 313142cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz case instrumentation::Instrumentation::kMethodExited: 313242cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz return &method_exit_event_ref_count_; 313342cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz case instrumentation::Instrumentation::kDexPcMoved: 313442cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz return &dex_pc_change_event_ref_count_; 313542cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz case instrumentation::Instrumentation::kFieldRead: 313642cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz return &field_read_event_ref_count_; 313742cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz case instrumentation::Instrumentation::kFieldWritten: 313842cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz return &field_write_event_ref_count_; 313942cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz case instrumentation::Instrumentation::kExceptionCaught: 314042cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz return &exception_catch_event_ref_count_; 314142cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz default: 314242cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz return nullptr; 314342cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz } 314442cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz} 314542cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz 31464d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz// Process request while all mutator threads are suspended. 31474d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertzvoid Dbg::ProcessDeoptimizationRequest(const DeoptimizationRequest& request) { 3148138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); 31490ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi switch (request.GetKind()) { 31504d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz case DeoptimizationRequest::kNothing: 31514d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz LOG(WARNING) << "Ignoring empty deoptimization request."; 31524d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz break; 315342cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz case DeoptimizationRequest::kRegisterForEvent: 315442cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz VLOG(jdwp) << StringPrintf("Add debugger as listener for instrumentation event 0x%x", 31550ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi request.InstrumentationEvent()); 31560ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi instrumentation->AddListener(&gDebugInstrumentationListener, request.InstrumentationEvent()); 31570ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi instrumentation_events_ |= request.InstrumentationEvent(); 315842cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz break; 315942cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz case DeoptimizationRequest::kUnregisterForEvent: 316042cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz VLOG(jdwp) << StringPrintf("Remove debugger as listener for instrumentation event 0x%x", 31610ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi request.InstrumentationEvent()); 316242cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz instrumentation->RemoveListener(&gDebugInstrumentationListener, 31630ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi request.InstrumentationEvent()); 31640ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi instrumentation_events_ &= ~request.InstrumentationEvent(); 316542cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz break; 31664d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz case DeoptimizationRequest::kFullDeoptimization: 31677ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz VLOG(jdwp) << "Deoptimize the world ..."; 31680462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertz instrumentation->DeoptimizeEverything(kDbgInstrumentationKey); 31697ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz VLOG(jdwp) << "Deoptimize the world DONE"; 31704d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz break; 31714d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz case DeoptimizationRequest::kFullUndeoptimization: 31727ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz VLOG(jdwp) << "Undeoptimize the world ..."; 31730462c4c87c39db6cfcd338f323844738109ac3c9Sebastien Hertz instrumentation->UndeoptimizeEverything(kDbgInstrumentationKey); 31747ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz VLOG(jdwp) << "Undeoptimize the world DONE"; 31754d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz break; 31764d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz case DeoptimizationRequest::kSelectiveDeoptimization: 3177709b070044354d9f47641f273edacaeeb0240ab7David Sehr VLOG(jdwp) << "Deoptimize method " << ArtMethod::PrettyMethod(request.Method()) << " ..."; 31780ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi instrumentation->Deoptimize(request.Method()); 3179709b070044354d9f47641f273edacaeeb0240ab7David Sehr VLOG(jdwp) << "Deoptimize method " << ArtMethod::PrettyMethod(request.Method()) << " DONE"; 31804d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz break; 31814d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz case DeoptimizationRequest::kSelectiveUndeoptimization: 3182709b070044354d9f47641f273edacaeeb0240ab7David Sehr VLOG(jdwp) << "Undeoptimize method " << ArtMethod::PrettyMethod(request.Method()) << " ..."; 31830ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi instrumentation->Undeoptimize(request.Method()); 3184709b070044354d9f47641f273edacaeeb0240ab7David Sehr VLOG(jdwp) << "Undeoptimize method " << ArtMethod::PrettyMethod(request.Method()) << " DONE"; 31854d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz break; 31864d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz default: 31870ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi LOG(FATAL) << "Unsupported deoptimization request kind " << request.GetKind(); 31884d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz break; 31894d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz } 31904d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz} 31914d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz 31924d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertzvoid Dbg::RequestDeoptimization(const DeoptimizationRequest& req) { 31930ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi if (req.GetKind() == DeoptimizationRequest::kNothing) { 31944d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz // Nothing to do. 31954d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz return; 31964d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz } 3197306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_); 31987ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz RequestDeoptimizationLocked(req); 31997ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz} 32007ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz 32017ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertzvoid Dbg::RequestDeoptimizationLocked(const DeoptimizationRequest& req) { 32020ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi switch (req.GetKind()) { 320342cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz case DeoptimizationRequest::kRegisterForEvent: { 32040ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi DCHECK_NE(req.InstrumentationEvent(), 0u); 32050ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi size_t* counter = GetReferenceCounterForEvent(req.InstrumentationEvent()); 320642cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz CHECK(counter != nullptr) << StringPrintf("No counter for instrumentation event 0x%x", 32070ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi req.InstrumentationEvent()); 320842cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz if (*counter == 0) { 32097d2ae437a87ceb2bdda098ab11f4da588c6a75f5Sebastien Hertz VLOG(jdwp) << StringPrintf("Queue request #%zd to start listening to instrumentation event 0x%x", 32100ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi deoptimization_requests_.size(), req.InstrumentationEvent()); 321142cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz deoptimization_requests_.push_back(req); 321242cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz } 321342cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz *counter = *counter + 1; 321442cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz break; 321542cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz } 321642cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz case DeoptimizationRequest::kUnregisterForEvent: { 32170ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi DCHECK_NE(req.InstrumentationEvent(), 0u); 32180ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi size_t* counter = GetReferenceCounterForEvent(req.InstrumentationEvent()); 321942cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz CHECK(counter != nullptr) << StringPrintf("No counter for instrumentation event 0x%x", 32200ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi req.InstrumentationEvent()); 322142cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz *counter = *counter - 1; 322242cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz if (*counter == 0) { 32237d2ae437a87ceb2bdda098ab11f4da588c6a75f5Sebastien Hertz VLOG(jdwp) << StringPrintf("Queue request #%zd to stop listening to instrumentation event 0x%x", 32240ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi deoptimization_requests_.size(), req.InstrumentationEvent()); 322542cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz deoptimization_requests_.push_back(req); 322642cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz } 322742cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz break; 322842cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz } 32294d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz case DeoptimizationRequest::kFullDeoptimization: { 32300ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi DCHECK(req.Method() == nullptr); 32314d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz if (full_deoptimization_event_count_ == 0) { 32327ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz VLOG(jdwp) << "Queue request #" << deoptimization_requests_.size() 32337ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz << " for full deoptimization"; 32344d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz deoptimization_requests_.push_back(req); 3235138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 32364d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz ++full_deoptimization_event_count_; 32374d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz break; 32384d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz } 32394d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz case DeoptimizationRequest::kFullUndeoptimization: { 32400ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi DCHECK(req.Method() == nullptr); 3241e713d9338ad122d6b8c7997387d0c9fc464eea3eSebastien Hertz DCHECK_GT(full_deoptimization_event_count_, 0U); 32424d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz --full_deoptimization_event_count_; 32434d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz if (full_deoptimization_event_count_ == 0) { 32447ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz VLOG(jdwp) << "Queue request #" << deoptimization_requests_.size() 32457ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz << " for full undeoptimization"; 32464d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz deoptimization_requests_.push_back(req); 3247138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 32484d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz break; 32494d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz } 32504d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz case DeoptimizationRequest::kSelectiveDeoptimization: { 32510ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi DCHECK(req.Method() != nullptr); 32527ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz VLOG(jdwp) << "Queue request #" << deoptimization_requests_.size() 3253709b070044354d9f47641f273edacaeeb0240ab7David Sehr << " for deoptimization of " << req.Method()->PrettyMethod(); 32544d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz deoptimization_requests_.push_back(req); 32554d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz break; 32564d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz } 32574d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz case DeoptimizationRequest::kSelectiveUndeoptimization: { 32580ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi DCHECK(req.Method() != nullptr); 32597ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz VLOG(jdwp) << "Queue request #" << deoptimization_requests_.size() 3260709b070044354d9f47641f273edacaeeb0240ab7David Sehr << " for undeoptimization of " << req.Method()->PrettyMethod(); 32614d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz deoptimization_requests_.push_back(req); 32624d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz break; 32634d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz } 32644d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz default: { 32650ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi LOG(FATAL) << "Unknown deoptimization request kind " << req.GetKind(); 32664d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz break; 3267138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 3268138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 3269138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz} 3270138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 3271138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertzvoid Dbg::ManageDeoptimization() { 3272138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz Thread* const self = Thread::Current(); 3273138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz { 3274138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz // Avoid suspend/resume if there is no pending request. 3275306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom MutexLock mu(self, *Locks::deoptimization_lock_); 32764d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz if (deoptimization_requests_.empty()) { 3277138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz return; 3278138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 3279138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 3280138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz CHECK_EQ(self->GetState(), kRunnable); 3281f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier ScopedThreadSuspension sts(self, kWaitingForDeoptimization); 3282aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier // Required for ProcessDeoptimizationRequest. 3283aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier gc::ScopedGCCriticalSection gcs(self, 3284aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier gc::kGcCauseInstrumentation, 3285aa5168291c46f9b418d989bccf2d8e09338a83e6Mathieu Chartier gc::kCollectorTypeInstrumentation); 3286138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz // We need to suspend mutator threads first. 32874f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier ScopedSuspendAll ssa(__FUNCTION__); 3288138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz const ThreadState old_state = self->SetStateUnsafe(kRunnable); 32894d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz { 3290306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom MutexLock mu(self, *Locks::deoptimization_lock_); 32917ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz size_t req_index = 0; 32920ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi for (DeoptimizationRequest& request : deoptimization_requests_) { 32937ec2f1ca3cbd021848da75d5566f7239ce29676fSebastien Hertz VLOG(jdwp) << "Process deoptimization request #" << req_index++; 32944d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz ProcessDeoptimizationRequest(request); 32954d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz } 32964d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz deoptimization_requests_.clear(); 32974d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz } 3298138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz CHECK_EQ(self->SetStateUnsafe(old_state), kRunnable); 3299138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz} 3300138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 3301e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic const Breakpoint* FindFirstBreakpointForMethod(ArtMethod* m) 3302bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_, Locks::breakpoint_lock_) { 33030ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi for (Breakpoint& breakpoint : gBreakpoints) { 33046c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light if (breakpoint.IsInMethod(m)) { 3305a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz return &breakpoint; 3306138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 3307a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz } 3308a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz return nullptr; 3309a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz} 3310138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 3311e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierbool Dbg::MethodHasAnyBreakpoints(ArtMethod* method) { 3312d8565456d29f4ad05f11cf84d2d2dac488508e06Mathieu Chartier ReaderMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_); 3313d8565456d29f4ad05f11cf84d2d2dac488508e06Mathieu Chartier return FindFirstBreakpointForMethod(method) != nullptr; 3314d8565456d29f4ad05f11cf84d2d2dac488508e06Mathieu Chartier} 3315d8565456d29f4ad05f11cf84d2d2dac488508e06Mathieu Chartier 3316a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz// Sanity checks all existing breakpoints on the same method. 3317e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic void SanityCheckExistingBreakpoints(ArtMethod* m, 3318f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz DeoptimizationRequest::Kind deoptimization_kind) 3319bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_, Locks::breakpoint_lock_) { 33204d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz for (const Breakpoint& breakpoint : gBreakpoints) { 33216c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light if (breakpoint.IsInMethod(m)) { 3322f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz CHECK_EQ(deoptimization_kind, breakpoint.GetDeoptimizationKind()); 3323f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz } 33244d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz } 3325f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); 3326f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz if (deoptimization_kind == DeoptimizationRequest::kFullDeoptimization) { 33274d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz // We should have deoptimized everything but not "selectively" deoptimized this method. 3328f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz CHECK(instrumentation->AreAllMethodsDeoptimized()); 3329f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz CHECK(!instrumentation->IsDeoptimized(m)); 3330f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz } else if (deoptimization_kind == DeoptimizationRequest::kSelectiveDeoptimization) { 33314d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz // We should have "selectively" deoptimized this method. 33324d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz // Note: while we have not deoptimized everything for this method, we may have done it for 33334d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz // another event. 3334f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz CHECK(instrumentation->IsDeoptimized(m)); 3335f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz } else { 3336f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz // This method does not require deoptimization. 3337f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz CHECK_EQ(deoptimization_kind, DeoptimizationRequest::kNothing); 3338f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz CHECK(!instrumentation->IsDeoptimized(m)); 3339138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 3340a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz} 3341138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz 3342abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz// Returns the deoptimization kind required to set a breakpoint in a method. 3343abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz// If a breakpoint has already been set, we also return the first breakpoint 3344abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz// through the given 'existing_brkpt' pointer. 3345f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertzstatic DeoptimizationRequest::Kind GetRequiredDeoptimizationKind(Thread* self, 3346e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m, 3347abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz const Breakpoint** existing_brkpt) 3348bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 3349f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz if (!Dbg::RequiresDeoptimization()) { 3350f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz // We already run in interpreter-only mode so we don't need to deoptimize anything. 3351f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz VLOG(jdwp) << "No need for deoptimization when fully running with interpreter for method " 3352709b070044354d9f47641f273edacaeeb0240ab7David Sehr << ArtMethod::PrettyMethod(m); 3353f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz return DeoptimizationRequest::kNothing; 3354f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz } 3355abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz const Breakpoint* first_breakpoint; 33564d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz { 33574d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz ReaderMutexLock mu(self, *Locks::breakpoint_lock_); 3358abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz first_breakpoint = FindFirstBreakpointForMethod(m); 3359abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz *existing_brkpt = first_breakpoint; 33604d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz } 3361abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz 3362abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz if (first_breakpoint == nullptr) { 33636300fd77033817664aee3056c4ff5fab85698d2bNicolas Geoffray // There is no breakpoint on this method yet: we need to deoptimize. If this method is default, 33646300fd77033817664aee3056c4ff5fab85698d2bNicolas Geoffray // we deoptimize everything; otherwise we deoptimize only this method. We 33656c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light // deoptimize with defaults because we do not know everywhere they are used. It is possible some 33666300fd77033817664aee3056c4ff5fab85698d2bNicolas Geoffray // of the copies could be missed. 33676c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light // TODO Deoptimizing on default methods might not be necessary in all cases. 33686300fd77033817664aee3056c4ff5fab85698d2bNicolas Geoffray bool need_full_deoptimization = m->IsDefault(); 3369a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz if (need_full_deoptimization) { 33706300fd77033817664aee3056c4ff5fab85698d2bNicolas Geoffray VLOG(jdwp) << "Need full deoptimization because of copying of method " 3371709b070044354d9f47641f273edacaeeb0240ab7David Sehr << ArtMethod::PrettyMethod(m); 3372f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz return DeoptimizationRequest::kFullDeoptimization; 3373a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz } else { 3374f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz // We don't need to deoptimize if the method has not been compiled. 3375a5891e81a2fb833307cf7c7e7267070dc0223dc8Nicolas Geoffray const bool is_compiled = m->HasAnyCompiledCode(); 3376f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz if (is_compiled) { 3377709b070044354d9f47641f273edacaeeb0240ab7David Sehr VLOG(jdwp) << "Need selective deoptimization for compiled method " 3378709b070044354d9f47641f273edacaeeb0240ab7David Sehr << ArtMethod::PrettyMethod(m); 33796300fd77033817664aee3056c4ff5fab85698d2bNicolas Geoffray return DeoptimizationRequest::kSelectiveDeoptimization; 3380f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz } else { 3381f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz // Method is not compiled: we don't need to deoptimize. 3382709b070044354d9f47641f273edacaeeb0240ab7David Sehr VLOG(jdwp) << "No need for deoptimization for non-compiled method " 3383709b070044354d9f47641f273edacaeeb0240ab7David Sehr << ArtMethod::PrettyMethod(m); 3384f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz return DeoptimizationRequest::kNothing; 3385f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz } 3386a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz } 3387a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz } else { 3388a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz // There is at least one breakpoint for this method: we don't need to deoptimize. 3389f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz // Let's check that all breakpoints are configured the same way for deoptimization. 3390f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz VLOG(jdwp) << "Breakpoint already set: no deoptimization is required"; 3391abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz DeoptimizationRequest::Kind deoptimization_kind = first_breakpoint->GetDeoptimizationKind(); 33924d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz if (kIsDebugBuild) { 33934d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz ReaderMutexLock mu(self, *Locks::breakpoint_lock_); 3394f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz SanityCheckExistingBreakpoints(m, deoptimization_kind); 33954d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz } 3396f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz return DeoptimizationRequest::kNothing; 3397f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz } 3398f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz} 3399f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz 3400f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz// Installs a breakpoint at the specified location. Also indicates through the deoptimization 3401f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz// request if we need to deoptimize. 3402f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertzvoid Dbg::WatchLocation(const JDWP::JdwpLocation* location, DeoptimizationRequest* req) { 3403f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz Thread* const self = Thread::Current(); 3404e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m = FromMethodId(location->method_id); 3405f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz DCHECK(m != nullptr) << "No method for method id " << location->method_id; 3406f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz 3407abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz const Breakpoint* existing_breakpoint = nullptr; 3408abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz const DeoptimizationRequest::Kind deoptimization_kind = 3409abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz GetRequiredDeoptimizationKind(self, m, &existing_breakpoint); 3410f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz req->SetKind(deoptimization_kind); 3411f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz if (deoptimization_kind == DeoptimizationRequest::kSelectiveDeoptimization) { 3412f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz req->SetMethod(m); 3413f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz } else { 3414f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz CHECK(deoptimization_kind == DeoptimizationRequest::kNothing || 3415f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz deoptimization_kind == DeoptimizationRequest::kFullDeoptimization); 3416f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz req->SetMethod(nullptr); 3417138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 3418a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz 34194d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz { 34204d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz WriterMutexLock mu(self, *Locks::breakpoint_lock_); 3421abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz // If there is at least one existing breakpoint on the same method, the new breakpoint 3422abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz // must have the same deoptimization kind than the existing breakpoint(s). 3423abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz DeoptimizationRequest::Kind breakpoint_deoptimization_kind; 3424abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz if (existing_breakpoint != nullptr) { 3425abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz breakpoint_deoptimization_kind = existing_breakpoint->GetDeoptimizationKind(); 3426abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz } else { 3427abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz breakpoint_deoptimization_kind = deoptimization_kind; 3428abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz } 3429abe93e0098a2648fa286cfea01954737e32c7be9Sebastien Hertz gBreakpoints.push_back(Breakpoint(m, location->dex_pc, breakpoint_deoptimization_kind)); 34304d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz VLOG(jdwp) << "Set breakpoint #" << (gBreakpoints.size() - 1) << ": " 34314d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz << gBreakpoints[gBreakpoints.size() - 1]; 34324d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz } 3433872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 3434872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 3435a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz// Uninstalls a breakpoint at the specified location. Also indicates through the deoptimization 3436a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz// request if we need to undeoptimize. 34374d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertzvoid Dbg::UnwatchLocation(const JDWP::JdwpLocation* location, DeoptimizationRequest* req) { 3438ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz WriterMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_); 3439e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m = FromMethodId(location->method_id); 3440a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz DCHECK(m != nullptr) << "No method for method id " << location->method_id; 3441f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz DeoptimizationRequest::Kind deoptimization_kind = DeoptimizationRequest::kNothing; 3442a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz for (size_t i = 0, e = gBreakpoints.size(); i < e; ++i) { 34436c8467ffc427a513dc2fdea7ed9eeb0bb54d30efAlex Light if (gBreakpoints[i].DexPc() == location->dex_pc && gBreakpoints[i].IsInMethod(m)) { 3444a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz VLOG(jdwp) << "Removed breakpoint #" << i << ": " << gBreakpoints[i]; 3445f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz deoptimization_kind = gBreakpoints[i].GetDeoptimizationKind(); 3446f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz DCHECK_EQ(deoptimization_kind == DeoptimizationRequest::kSelectiveDeoptimization, 3447f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz Runtime::Current()->GetInstrumentation()->IsDeoptimized(m)); 3448a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz gBreakpoints.erase(gBreakpoints.begin() + i); 3449a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz break; 3450138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 3451138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz } 3452a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz const Breakpoint* const existing_breakpoint = FindFirstBreakpointForMethod(m); 3453a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz if (existing_breakpoint == nullptr) { 3454a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz // There is no more breakpoint on this method: we need to undeoptimize. 3455f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz if (deoptimization_kind == DeoptimizationRequest::kFullDeoptimization) { 3456a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz // This method required full deoptimization: we need to undeoptimize everything. 34570ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi req->SetKind(DeoptimizationRequest::kFullUndeoptimization); 34580ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi req->SetMethod(nullptr); 3459f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz } else if (deoptimization_kind == DeoptimizationRequest::kSelectiveDeoptimization) { 3460a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz // This method required selective deoptimization: we need to undeoptimize only that method. 34610ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi req->SetKind(DeoptimizationRequest::kSelectiveUndeoptimization); 34620ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi req->SetMethod(m); 3463f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz } else { 3464f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz // This method had no need for deoptimization: do nothing. 3465f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz CHECK_EQ(deoptimization_kind, DeoptimizationRequest::kNothing); 3466f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz req->SetKind(DeoptimizationRequest::kNothing); 3467f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz req->SetMethod(nullptr); 3468a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz } 3469a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz } else { 3470a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz // There is at least one breakpoint for this method: we don't need to undeoptimize. 34710ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi req->SetKind(DeoptimizationRequest::kNothing); 34720ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi req->SetMethod(nullptr); 34734d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz if (kIsDebugBuild) { 3474f3928794a10516e2ac0ffe2686a10891788d4b9cSebastien Hertz SanityCheckExistingBreakpoints(m, deoptimization_kind); 34754d1e9ab57e4c822e8e678b1d0c1d6ad2abfa9b3eSebastien Hertz } 34768696433d1b3d8ba15288483b777edd888de69135Elliott Hughes } 3477872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 3478872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 3479e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierbool Dbg::IsForcedInterpreterNeededForCallingImpl(Thread* thread, ArtMethod* m) { 3480eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi const SingleStepControl* const ssc = thread->GetSingleStepControl(); 3481eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (ssc == nullptr) { 3482eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // If we are not single-stepping, then we don't have to force interpreter. 3483eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return false; 3484eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 3485eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (Runtime::Current()->GetInstrumentation()->InterpretOnly()) { 3486eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // If we are in interpreter only mode, then we don't have to force interpreter. 3487eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return false; 3488eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 3489eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi 3490eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (!m->IsNative() && !m->IsProxyMethod()) { 3491eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // If we want to step into a method, then we have to force interpreter on that call. 3492eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (ssc->GetStepDepth() == JDWP::SD_INTO) { 3493eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return true; 3494eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 3495eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 3496eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return false; 3497eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi} 3498eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi 3499e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierbool Dbg::IsForcedInterpreterNeededForResolutionImpl(Thread* thread, ArtMethod* m) { 3500eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi instrumentation::Instrumentation* const instrumentation = 3501eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi Runtime::Current()->GetInstrumentation(); 3502eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // If we are in interpreter only mode, then we don't have to force interpreter. 3503eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (instrumentation->InterpretOnly()) { 3504eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return false; 3505eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 3506eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // We can only interpret pure Java method. 3507eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (m->IsNative() || m->IsProxyMethod()) { 3508eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return false; 3509eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 3510eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi const SingleStepControl* const ssc = thread->GetSingleStepControl(); 3511eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (ssc != nullptr) { 3512eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // If we want to step into a method, then we have to force interpreter on that call. 3513eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (ssc->GetStepDepth() == JDWP::SD_INTO) { 3514eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return true; 3515eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 3516eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // If we are stepping out from a static initializer, by issuing a step 3517eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // in or step over, that was implicitly invoked by calling a static method, 3518eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // then we need to step into that method. Having a lower stack depth than 3519eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // the one the single step control has indicates that the step originates 3520eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // from the static initializer. 3521eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (ssc->GetStepDepth() != JDWP::SD_OUT && 3522eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi ssc->GetStackDepth() > GetStackDepth(thread)) { 3523eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return true; 3524eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 3525eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 3526eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // There are cases where we have to force interpreter on deoptimized methods, 3527eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // because in some cases the call will not be performed by invoking an entry 3528eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // point that has been replaced by the deoptimization, but instead by directly 3529eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // invoking the compiled code of the method, for example. 3530eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return instrumentation->IsDeoptimized(m); 3531eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi} 3532eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi 3533e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierbool Dbg::IsForcedInstrumentationNeededForResolutionImpl(Thread* thread, ArtMethod* m) { 35342cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier // The upcall can be null and in that case we don't need to do anything. 3535eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (m == nullptr) { 3536eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return false; 3537eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 3538eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi instrumentation::Instrumentation* const instrumentation = 3539eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi Runtime::Current()->GetInstrumentation(); 3540eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // If we are in interpreter only mode, then we don't have to force interpreter. 3541eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (instrumentation->InterpretOnly()) { 3542eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return false; 3543eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 3544eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // We can only interpret pure Java method. 3545eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (m->IsNative() || m->IsProxyMethod()) { 3546eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return false; 3547eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 3548eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi const SingleStepControl* const ssc = thread->GetSingleStepControl(); 3549eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (ssc != nullptr) { 3550eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // If we are stepping out from a static initializer, by issuing a step 3551eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // out, that was implicitly invoked by calling a static method, then we 3552eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // need to step into the caller of that method. Having a lower stack 3553eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // depth than the one the single step control has indicates that the 3554eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // step originates from the static initializer. 3555eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (ssc->GetStepDepth() == JDWP::SD_OUT && 3556eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi ssc->GetStackDepth() > GetStackDepth(thread)) { 3557eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return true; 3558eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 3559eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 3560eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // If we are returning from a static intializer, that was implicitly 3561eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // invoked by calling a static method and the caller is deoptimized, 3562eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // then we have to deoptimize the stack without forcing interpreter 3563eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // on the static method that was called originally. This problem can 3564eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // be solved easily by forcing instrumentation on the called method, 3565eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // because the instrumentation exit hook will recognise the need of 3566eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // stack deoptimization by calling IsForcedInterpreterNeededForUpcall. 3567eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return instrumentation->IsDeoptimized(m); 3568eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi} 3569eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi 3570e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierbool Dbg::IsForcedInterpreterNeededForUpcallImpl(Thread* thread, ArtMethod* m) { 35712cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier // The upcall can be null and in that case we don't need to do anything. 3572eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (m == nullptr) { 3573eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return false; 3574eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 3575eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi instrumentation::Instrumentation* const instrumentation = 3576eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi Runtime::Current()->GetInstrumentation(); 3577eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // If we are in interpreter only mode, then we don't have to force interpreter. 3578eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (instrumentation->InterpretOnly()) { 3579eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return false; 3580eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 3581eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // We can only interpret pure Java method. 3582eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (m->IsNative() || m->IsProxyMethod()) { 3583eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return false; 3584eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 3585eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi const SingleStepControl* const ssc = thread->GetSingleStepControl(); 3586eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (ssc != nullptr) { 3587eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // The debugger is not interested in what is happening under the level 3588eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // of the step, thus we only force interpreter when we are not below of 3589eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // the step. 3590eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (ssc->GetStackDepth() >= GetStackDepth(thread)) { 3591eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return true; 3592eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 3593eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 359499170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang if (thread->HasDebuggerShadowFrames()) { 359599170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang // We need to deoptimize the stack for the exception handling flow so that 359699170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang // we don't miss any deoptimization that should be done when there are 359799170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang // debugger shadow frames. 359899170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang return true; 359999170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang } 3600eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // We have to require stack deoptimization if the upcall is deoptimized. 3601eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi return instrumentation->IsDeoptimized(m); 3602eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi} 3603eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi 360499170c636dfae4908b102347cfe9f92bad1881ccMingyao Yangclass NeedsDeoptimizationVisitor : public StackVisitor { 3605520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz public: 3606520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz explicit NeedsDeoptimizationVisitor(Thread* self) 3607bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) 3608520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz : StackVisitor(self, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), 3609520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz needs_deoptimization_(false) {} 3610520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz 3611bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { 3612520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz // The visitor is meant to be used when handling exception from compiled code only. 3613709b070044354d9f47641f273edacaeeb0240ab7David Sehr CHECK(!IsShadowFrame()) << "We only expect to visit compiled frame: " 3614709b070044354d9f47641f273edacaeeb0240ab7David Sehr << ArtMethod::PrettyMethod(GetMethod()); 3615520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz ArtMethod* method = GetMethod(); 3616520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz if (method == nullptr) { 3617520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz // We reach an upcall and don't need to deoptimize this part of the stack (ManagedFragment) 3618520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz // so we can stop the visit. 3619520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz DCHECK(!needs_deoptimization_); 3620520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz return false; 3621520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz } 3622520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz if (Runtime::Current()->GetInstrumentation()->InterpretOnly()) { 3623520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz // We found a compiled frame in the stack but instrumentation is set to interpret 3624520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz // everything: we need to deoptimize. 3625520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz needs_deoptimization_ = true; 3626520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz return false; 3627520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz } 3628520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz if (Runtime::Current()->GetInstrumentation()->IsDeoptimized(method)) { 3629520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz // We found a deoptimized method in the stack. 3630520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz needs_deoptimization_ = true; 3631520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz return false; 3632520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz } 363399170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang ShadowFrame* frame = GetThread()->FindDebuggerShadowFrame(GetFrameId()); 363499170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang if (frame != nullptr) { 363599170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang // The debugger allocated a ShadowFrame to update a variable in the stack: we need to 363699170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang // deoptimize the stack to execute (and deallocate) this frame. 363799170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang needs_deoptimization_ = true; 363899170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang return false; 363999170c636dfae4908b102347cfe9f92bad1881ccMingyao Yang } 3640520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz return true; 3641520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz } 3642520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz 3643520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz bool NeedsDeoptimization() const { 3644520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz return needs_deoptimization_; 3645520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz } 3646520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz 3647520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz private: 3648520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz // Do we need to deoptimize the stack? 3649520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz bool needs_deoptimization_; 3650520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz 3651520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz DISALLOW_COPY_AND_ASSIGN(NeedsDeoptimizationVisitor); 3652520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz}; 3653520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz 3654520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz// Do we need to deoptimize the stack to handle an exception? 3655520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertzbool Dbg::IsForcedInterpreterNeededForExceptionImpl(Thread* thread) { 3656520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz const SingleStepControl* const ssc = thread->GetSingleStepControl(); 3657520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz if (ssc != nullptr) { 3658520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz // We deopt to step into the catch handler. 3659520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz return true; 3660520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz } 3661520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz // Deoptimization is required if at least one method in the stack needs it. However we 3662520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz // skip frames that will be unwound (thus not executed). 3663520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz NeedsDeoptimizationVisitor visitor(thread); 3664520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz visitor.WalkStack(true); // includes upcall. 3665520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz return visitor.NeedsDeoptimization(); 3666520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz} 3667520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz 3668449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao// Scoped utility class to suspend a thread so that we may do tasks such as walk its stack. Doesn't 3669449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao// cause suspension if the thread is the current thread. 3670f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartierclass ScopedDebuggerThreadSuspension { 3671449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao public: 3672f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier ScopedDebuggerThreadSuspension(Thread* self, JDWP::ObjectId thread_id) 367390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier REQUIRES(!Locks::thread_list_lock_) 3674bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) : 3675f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers thread_(nullptr), 3676449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao error_(JDWP::ERR_NONE), 3677449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao self_suspend_(false), 367833e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogers other_suspend_(false) { 3679449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao ScopedObjectAccessUnchecked soa(self); 3680692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz thread_ = DecodeThread(soa, thread_id, &error_); 3681449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao if (error_ == JDWP::ERR_NONE) { 3682449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao if (thread_ == soa.Self()) { 3683449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao self_suspend_ = true; 3684449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } else { 3685f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier Thread* suspended_thread; 3686f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier { 3687f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier ScopedThreadSuspension sts(self, kWaitingForDebuggerSuspension); 3688f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier jobject thread_peer = Dbg::GetObjectRegistry()->GetJObject(thread_id); 3689f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier bool timed_out; 3690f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier ThreadList* const thread_list = Runtime::Current()->GetThreadList(); 3691cdd798de1b2e7807f1cab8ebbfbb165069beae6bSebastien Hertz suspended_thread = thread_list->SuspendThreadByPeer(thread_peer, 3692cdd798de1b2e7807f1cab8ebbfbb165069beae6bSebastien Hertz /* request_suspension */ true, 3693cdd798de1b2e7807f1cab8ebbfbb165069beae6bSebastien Hertz /* debug_suspension */ true, 3694cdd798de1b2e7807f1cab8ebbfbb165069beae6bSebastien Hertz &timed_out); 3695f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier } 3696f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers if (suspended_thread == nullptr) { 3697449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao // Thread terminated from under us while suspending. 3698449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao error_ = JDWP::ERR_INVALID_THREAD; 3699449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } else { 3700449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao CHECK_EQ(suspended_thread, thread_); 3701449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao other_suspend_ = true; 3702449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } 3703449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } 3704449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } 3705449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } 3706449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao 3707449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao Thread* GetThread() const { 3708449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao return thread_; 3709449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } 3710449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao 3711449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao JDWP::JdwpError GetError() const { 3712449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao return error_; 3713449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } 3714449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao 3715f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier ~ScopedDebuggerThreadSuspension() { 3716449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao if (other_suspend_) { 3717449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao Runtime::Current()->GetThreadList()->Resume(thread_, true); 3718449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } 3719449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao } 3720449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao 3721449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao private: 3722449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao Thread* thread_; 3723449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao JDWP::JdwpError error_; 3724449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao bool self_suspend_; 3725449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao bool other_suspend_; 3726449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao}; 3727449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao 3728221229cb523f849f165fdafbf9785010963715daElliott HughesJDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize step_size, 372900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JDWP::JdwpStepDepth step_depth) { 3730449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao Thread* self = Thread::Current(); 3731f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier ScopedDebuggerThreadSuspension sts(self, thread_id); 3732449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao if (sts.GetError() != JDWP::ERR_NONE) { 3733449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao return sts.GetError(); 37342435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 37358696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 3736597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz // Work out what ArtMethod* we're in, the current line number, and how deep the stack currently 37372435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // is for step-out. 37380399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers struct SingleStepStackVisitor : public StackVisitor { 3739bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe explicit SingleStepStackVisitor(Thread* thread) REQUIRES_SHARED(Locks::mutator_lock_) 37408e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), 37418e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray stack_depth(0), 37428e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray method(nullptr), 37438e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray line_number(-1) {} 3744ca190666fb11820153f74274c495ba1f913d8a69Ian Rogers 374500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses 374600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // annotalysis. 374700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { 3748e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m = GetMethod(); 37490399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers if (!m->IsRuntimeMethod()) { 3750597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz ++stack_depth; 3751597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz if (method == nullptr) { 37527337631929812fb8a60b5182eba076a32d1cb851Alex Light const DexFile* dex_file = m->GetDexFile(); 3753597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz method = m; 37547337631929812fb8a60b5182eba076a32d1cb851Alex Light if (dex_file != nullptr) { 37559323e6e44060545d6c4f925139572868f65b7fe3David Sehr line_number = annotations::GetLineNumFromPC(dex_file, m, GetDexPc()); 37562435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 37578696433d1b3d8ba15288483b777edd888de69135Elliott Hughes } 37588696433d1b3d8ba15288483b777edd888de69135Elliott Hughes } 3759530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return true; 37608696433d1b3d8ba15288483b777edd888de69135Elliott Hughes } 376161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz 3762597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz int stack_depth; 3763e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* method; 3764597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz int32_t line_number; 37658696433d1b3d8ba15288483b777edd888de69135Elliott Hughes }; 3766449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao 376761b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz Thread* const thread = sts.GetThread(); 3768597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz SingleStepStackVisitor visitor(thread); 37690399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers visitor.WalkStack(); 37708696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 37712435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // Find the dex_pc values that correspond to the current line, for line-based single-stepping. 37722435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes struct DebugCallbackContext { 37733887c468d731420e929e6ad3acf190d5431e94fcRoland Levillain DebugCallbackContext(SingleStepControl* single_step_control_cb, 37743887c468d731420e929e6ad3acf190d5431e94fcRoland Levillain int32_t line_number_cb, const DexFile::CodeItem* code_item) 37753887c468d731420e929e6ad3acf190d5431e94fcRoland Levillain : single_step_control_(single_step_control_cb), line_number_(line_number_cb), 37763887c468d731420e929e6ad3acf190d5431e94fcRoland Levillain code_item_(code_item), last_pc_valid(false), last_pc(0) { 37772435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 37782435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 3779b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky static bool Callback(void* raw_context, const DexFile::PositionInfo& entry) { 37802435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes DebugCallbackContext* context = reinterpret_cast<DebugCallbackContext*>(raw_context); 3781b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky if (static_cast<int32_t>(entry.line_) == context->line_number_) { 37822435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes if (!context->last_pc_valid) { 37832435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // Everything from this address until the next line change is ours. 3784b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky context->last_pc = entry.address_; 37852435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes context->last_pc_valid = true; 37862435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 37872435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // Otherwise, if we're already in a valid range for this line, 37882435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // just keep going (shouldn't really happen)... 37897934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (context->last_pc_valid) { // and the line number is new 37902435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // Add everything from the last entry up until here to the set 3791b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky for (uint32_t dex_pc = context->last_pc; dex_pc < entry.address_; ++dex_pc) { 3792597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz context->single_step_control_->AddDexPc(dex_pc); 37932435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 37942435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes context->last_pc_valid = false; 37952435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 37967934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom return false; // There may be multiple entries for any given line. 37972435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 37982435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 379961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz ~DebugCallbackContext() { 38002435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes // If the line number was the last in the position table... 38012435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes if (last_pc_valid) { 3802bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz size_t end = code_item_->insns_size_in_code_units_; 38032435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes for (uint32_t dex_pc = last_pc; dex_pc < end; ++dex_pc) { 3804597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz single_step_control_->AddDexPc(dex_pc); 38052435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 38062435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 38072435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 38082435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 380961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz SingleStepControl* const single_step_control_; 381061b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz const int32_t line_number_; 3811bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz const DexFile::CodeItem* const code_item_; 38122435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes bool last_pc_valid; 38132435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes uint32_t last_pc; 38142435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes }; 3815597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz 3816597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz // Allocate single step. 38171558b577907b613864e98f05862543557263e864Sebastien Hertz SingleStepControl* single_step_control = 38181558b577907b613864e98f05862543557263e864Sebastien Hertz new (std::nothrow) SingleStepControl(step_size, step_depth, 38191558b577907b613864e98f05862543557263e864Sebastien Hertz visitor.stack_depth, visitor.method); 38201558b577907b613864e98f05862543557263e864Sebastien Hertz if (single_step_control == nullptr) { 38211558b577907b613864e98f05862543557263e864Sebastien Hertz LOG(ERROR) << "Failed to allocate SingleStepControl"; 38221558b577907b613864e98f05862543557263e864Sebastien Hertz return JDWP::ERR_OUT_OF_MEMORY; 38231558b577907b613864e98f05862543557263e864Sebastien Hertz } 38241558b577907b613864e98f05862543557263e864Sebastien Hertz 3825e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m = single_step_control->GetMethod(); 3826597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz const int32_t line_number = visitor.line_number; 382752f5f93873ec244320e05b033243c5c7a3ae40e2Sebastien Hertz // Note: if the thread is not running Java code (pure native thread), there is no "current" 382852f5f93873ec244320e05b033243c5c7a3ae40e2Sebastien Hertz // method on the stack (and no line number either). 382952f5f93873ec244320e05b033243c5c7a3ae40e2Sebastien Hertz if (m != nullptr && !m->IsNative()) { 3830bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier const DexFile::CodeItem* const code_item = m->GetCodeItem(); 3831bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz DebugCallbackContext context(single_step_control, line_number, code_item); 3832b06e28e5b9fbabe3e69b18f31bf353eaff5d0c1fDavid Srbecky m->GetDexFile()->DecodeDebugPositionInfo(code_item, DebugCallbackContext::Callback, &context); 38333e2e1a2380e7b2ce402640ea4f6a177c06bd19a2Elliott Hughes } 38342435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 3835597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz // Activate single-step in the thread. 3836597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz thread->ActivateSingleStepControl(single_step_control); 38378696433d1b3d8ba15288483b777edd888de69135Elliott Hughes 38382435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes if (VLOG_IS_ON(jdwp)) { 383961b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz VLOG(jdwp) << "Single-step thread: " << *thread; 3840597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz VLOG(jdwp) << "Single-step step size: " << single_step_control->GetStepSize(); 3841597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz VLOG(jdwp) << "Single-step step depth: " << single_step_control->GetStepDepth(); 3842709b070044354d9f47641f273edacaeeb0240ab7David Sehr VLOG(jdwp) << "Single-step current method: " 3843709b070044354d9f47641f273edacaeeb0240ab7David Sehr << ArtMethod::PrettyMethod(single_step_control->GetMethod()); 384461b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz VLOG(jdwp) << "Single-step current line: " << line_number; 3845597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz VLOG(jdwp) << "Single-step current stack depth: " << single_step_control->GetStackDepth(); 38462435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes VLOG(jdwp) << "Single-step dex_pc values:"; 3847597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz for (uint32_t dex_pc : single_step_control->GetDexPcs()) { 3848bb43b433c845e253a11346f0f03706d58a44f23cSebastien Hertz VLOG(jdwp) << StringPrintf(" %#x", dex_pc); 38492435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 38502435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes } 38512435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes 38522435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes return JDWP::ERR_NONE; 3853872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 3854872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 385561b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertzvoid Dbg::UnconfigureStep(JDWP::ObjectId thread_id) { 385661b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz ScopedObjectAccessUnchecked soa(Thread::Current()); 3857c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 3858c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers Thread* thread = DecodeThread(soa, thread_id, &error); 385987118ed6f3f99e7df33214c277cf200a7b9a7499Sebastien Hertz if (error == JDWP::ERR_NONE) { 3860597c4f0aeafed2b6fa69e53ece4be4f53115d707Sebastien Hertz thread->DeactivateSingleStepControl(); 386161b7f1b05d1fe12d4009316263bf990903e4edffSebastien Hertz } 3862872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 3863872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 386445651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughesstatic char JdwpTagToShortyChar(JDWP::JdwpTag tag) { 386545651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes switch (tag) { 386645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes default: 386745651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes LOG(FATAL) << "unknown JDWP tag: " << PrintableChar(tag); 3868fc787ecd91127b2c8458afd94e5148e2ae51a1f5Ian Rogers UNREACHABLE(); 386945651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes 387045651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes // Primitives. 387145651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_BYTE: return 'B'; 387245651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_CHAR: return 'C'; 387345651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_FLOAT: return 'F'; 387445651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_DOUBLE: return 'D'; 387545651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_INT: return 'I'; 387645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_LONG: return 'J'; 387745651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_SHORT: return 'S'; 387845651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_VOID: return 'V'; 387945651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_BOOLEAN: return 'Z'; 388045651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes 388145651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes // Reference types. 388245651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_ARRAY: 388345651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_OBJECT: 388445651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_STRING: 388545651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_THREAD: 388645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_THREAD_GROUP: 388745651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_CLASS_LOADER: 388845651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes case JDWP::JT_CLASS_OBJECT: 388945651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes return 'L'; 389045651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } 389145651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes} 389245651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes 3893cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien HertzJDWP::JdwpError Dbg::PrepareInvokeMethod(uint32_t request_id, JDWP::ObjectId thread_id, 3894cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz JDWP::ObjectId object_id, JDWP::RefTypeId class_id, 3895cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz JDWP::MethodId method_id, uint32_t arg_count, 3896cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz uint64_t arg_values[], JDWP::JdwpTag* arg_types, 3897cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz uint32_t options) { 3898cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz Thread* const self = Thread::Current(); 3899cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz CHECK_EQ(self, GetDebugThread()) << "This must be called by the JDWP thread"; 3900d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz const bool resume_all_threads = ((options & JDWP::INVOKE_SINGLE_THREADED) == 0); 3901d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 3902cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz ThreadList* thread_list = Runtime::Current()->GetThreadList(); 3903c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers Thread* targetThread = nullptr; 3904d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes { 390500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(self); 3906c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers JDWP::JdwpError error; 3907c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers targetThread = DecodeThread(soa, thread_id, &error); 3908221229cb523f849f165fdafbf9785010963715daElliott Hughes if (error != JDWP::ERR_NONE) { 3909221229cb523f849f165fdafbf9785010963715daElliott Hughes LOG(ERROR) << "InvokeMethod request for invalid thread id " << thread_id; 3910221229cb523f849f165fdafbf9785010963715daElliott Hughes return error; 3911d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 39121558b577907b613864e98f05862543557263e864Sebastien Hertz if (targetThread->GetInvokeReq() != nullptr) { 39131558b577907b613864e98f05862543557263e864Sebastien Hertz // Thread is already invoking a method on behalf of the debugger. 39141558b577907b613864e98f05862543557263e864Sebastien Hertz LOG(ERROR) << "InvokeMethod request for thread already invoking a method: " << *targetThread; 39151558b577907b613864e98f05862543557263e864Sebastien Hertz return JDWP::ERR_ALREADY_INVOKING; 39161558b577907b613864e98f05862543557263e864Sebastien Hertz } 39171558b577907b613864e98f05862543557263e864Sebastien Hertz if (!targetThread->IsReadyForDebugInvoke()) { 39181558b577907b613864e98f05862543557263e864Sebastien Hertz // Thread is not suspended by an event so it cannot invoke a method. 3919d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes LOG(ERROR) << "InvokeMethod request for thread not stopped by event: " << *targetThread; 3920d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes return JDWP::ERR_INVALID_THREAD; 3921d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 3922d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 3923d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes /* 3924d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz * According to the JDWP specs, we are expected to resume all threads (or only the 3925d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz * target thread) once. So if a thread has been suspended more than once (either by 3926d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz * the debugger for an event or by the runtime for GC), it will remain suspended before 3927d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz * the invoke is executed. This means the debugger is responsible to properly resume all 3928d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz * the threads it has suspended so the target thread can execute the method. 3929d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes * 3930d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz * However, for compatibility reason with older versions of debuggers (like Eclipse), we 3931d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz * fully resume all threads (by canceling *all* debugger suspensions) when the debugger 3932d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz * wants us to resume all threads. This is to avoid ending up in deadlock situation. 3933d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz * 3934d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz * On the other hand, if we are asked to only resume the target thread, then we follow the 3935d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz * JDWP specs by resuming that thread only once. This means the thread will remain suspended 3936d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz * if it has been suspended more than once before the invoke (and again, this is the 3937d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz * responsibility of the debugger to properly resume that thread before invoking a method). 3938d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes */ 393900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers int suspend_count; 394000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers { 394150b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_); 394200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers suspend_count = targetThread->GetSuspendCount(); 394300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 3944d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz if (suspend_count > 1 && resume_all_threads) { 3945d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz // The target thread will remain suspended even after we resume it. Let's emit a warning 3946d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz // to indicate the invoke won't be executed until the thread is resumed. 3947d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz LOG(WARNING) << *targetThread << " suspended more than once (suspend count == " 3948d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz << suspend_count << "). This thread will invoke the method only once " 3949d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz << "it is fully resumed."; 3950d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 3951d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 3952c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Object* receiver = gRegistry->Get<mirror::Object*>(object_id, &error); 3953c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (error != JDWP::ERR_NONE) { 39543f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 39553f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes } 395645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes 39571558b577907b613864e98f05862543557263e864Sebastien Hertz gRegistry->Get<mirror::Object*>(thread_id, &error); 3958c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (error != JDWP::ERR_NONE) { 39593f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes return JDWP::ERR_INVALID_OBJECT; 39603f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes } 396145651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes 3962c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Class* c = DecodeClass(class_id, &error); 3963c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (c == nullptr) { 3964c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers return error; 39653f4d58f4a39f60057ebf8ea92340ddb78317ae51Elliott Hughes } 396645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes 3967e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m = FromMethodId(method_id); 3968c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (m->IsStatic() != (receiver == nullptr)) { 396945651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes return JDWP::ERR_INVALID_METHODID; 397045651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } 397145651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes if (m->IsStatic()) { 397245651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes if (m->GetDeclaringClass() != c) { 397345651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes return JDWP::ERR_INVALID_METHODID; 397445651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } 397545651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } else { 397645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes if (!m->GetDeclaringClass()->IsAssignableFrom(c)) { 397745651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes return JDWP::ERR_INVALID_METHODID; 397845651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } 397945651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } 398045651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes 398145651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes // Check the argument list matches the method. 3982bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier uint32_t shorty_len = 0; 3983bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier const char* shorty = m->GetShorty(&shorty_len); 3984bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier if (shorty_len - 1 != arg_count) { 398545651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes return JDWP::ERR_ILLEGAL_ARGUMENT; 398645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } 39870920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes 3988bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier { 3989e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier StackHandleScope<2> hs(soa.Self()); 3990bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&receiver)); 3991bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier HandleWrapper<mirror::Class> h_klass(hs.NewHandleWrapper(&c)); 3992bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier const DexFile::TypeList* types = m->GetParameterTypeList(); 3993bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier for (size_t i = 0; i < arg_count; ++i) { 3994bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier if (shorty[i + 1] != JdwpTagToShortyChar(arg_types[i])) { 39950920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes return JDWP::ERR_ILLEGAL_ARGUMENT; 39960920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes } 39970920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes 3998bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier if (shorty[i + 1] == 'L') { 3999bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier // Did we really get an argument of an appropriate reference type? 4000a0485607a4a4d8c683a9849f6f20902c4e1da7a4Ian Rogers mirror::Class* parameter_type = 4001942fd3130254d8276cbfe8e6201825e9c49e9b2cVladimir Marko m->GetClassFromTypeIndex(types->GetTypeItem(i).type_idx_, true /* resolve */); 4002c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers mirror::Object* argument = gRegistry->Get<mirror::Object*>(arg_values[i], &error); 4003c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (error != JDWP::ERR_NONE) { 4004bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier return JDWP::ERR_INVALID_OBJECT; 4005bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier } 4006c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (argument != nullptr && !argument->InstanceOf(parameter_type)) { 4007bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier return JDWP::ERR_ILLEGAL_ARGUMENT; 4008bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier } 4009bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier 4010bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier // Turn the on-the-wire ObjectId into a jobject. 4011bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier jvalue& v = reinterpret_cast<jvalue&>(arg_values[i]); 4012bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier v.l = gRegistry->GetJObject(arg_values[i]); 4013bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier } 40140920163b0ee4ce3fbf57db5506659de14b77be75Elliott Hughes } 401545651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } 401645651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes 40171558b577907b613864e98f05862543557263e864Sebastien Hertz // Allocates a DebugInvokeReq. 4018cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz DebugInvokeReq* req = new (std::nothrow) DebugInvokeReq(request_id, thread_id, receiver, c, m, 4019cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz options, arg_values, arg_count); 4020cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz if (req == nullptr) { 40211558b577907b613864e98f05862543557263e864Sebastien Hertz LOG(ERROR) << "Failed to allocate DebugInvokeReq"; 40221558b577907b613864e98f05862543557263e864Sebastien Hertz return JDWP::ERR_OUT_OF_MEMORY; 40231558b577907b613864e98f05862543557263e864Sebastien Hertz } 40241558b577907b613864e98f05862543557263e864Sebastien Hertz 4025cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // Attaches the DebugInvokeReq to the target thread so it executes the method when 4026cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // it is resumed. Once the invocation completes, the target thread will delete it before 4027cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // suspending itself (see ThreadList::SuspendSelfForDebugger). 4028cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz targetThread->SetDebugInvokeReq(req); 4029d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 4030d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 4031d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes // The fact that we've released the thread list lock is a bit risky --- if the thread goes 4032cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // away we're sitting high and dry -- but we must release this before the UndoDebuggerSuspensions 4033cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // call. 4034d4032e4e2d454b11dba74acc4824abb8a846f707Sebastien Hertz if (resume_all_threads) { 4035cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz VLOG(jdwp) << " Resuming all threads"; 4036cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz thread_list->UndoDebuggerSuspensions(); 4037cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz } else { 4038cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz VLOG(jdwp) << " Resuming event thread only"; 4039d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes thread_list->Resume(targetThread, true); 4040d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 4041d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 4042cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz return JDWP::ERR_NONE; 4043872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 4044872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 4045872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::ExecuteMethod(DebugInvokeReq* pReq) { 4046cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz Thread* const self = Thread::Current(); 4047cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz CHECK_NE(self, GetDebugThread()) << "This must be called by the event thread"; 4048cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz 4049cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz ScopedObjectAccess soa(self); 4050d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 405181ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes // We can be called while an exception is pending. We need 4052d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes // to preserve that across the method invocation. 4053cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz StackHandleScope<1> hs(soa.Self()); 4054cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz Handle<mirror::Throwable> old_exception = hs.NewHandle(soa.Self()->GetException()); 40551558b577907b613864e98f05862543557263e864Sebastien Hertz soa.Self()->ClearException(); 4056d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 4057cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // Execute the method then sends reply to the debugger. 4058cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz ExecuteMethodWithoutPendingException(soa, pReq); 4059cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz 4060cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // If an exception was pending before the invoke, restore it now. 4061fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe if (old_exception != nullptr) { 4062cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz soa.Self()->SetException(old_exception.Get()); 4063cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz } 4064cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz} 4065cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz 4066cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz// Helper function: write a variable-width value into the output input buffer. 4067cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertzstatic void WriteValue(JDWP::ExpandBuf* pReply, int width, uint64_t value) { 4068cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz switch (width) { 4069cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz case 1: 4070cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz expandBufAdd1(pReply, value); 4071cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz break; 4072cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz case 2: 4073cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz expandBufAdd2BE(pReply, value); 4074cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz break; 4075cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz case 4: 4076cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz expandBufAdd4BE(pReply, value); 4077cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz break; 4078cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz case 8: 4079cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz expandBufAdd8BE(pReply, value); 4080cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz break; 4081cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz default: 4082cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz LOG(FATAL) << width; 4083cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz UNREACHABLE(); 4084cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz } 4085cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz} 4086cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz 4087cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertzvoid Dbg::ExecuteMethodWithoutPendingException(ScopedObjectAccess& soa, DebugInvokeReq* pReq) { 4088cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz soa.Self()->AssertNoPendingException(); 4089cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz 4090d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes // Translate the method through the vtable, unless the debugger wants to suppress it. 4091cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz ArtMethod* m = pReq->method; 4092542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe PointerSize image_pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize(); 40931558b577907b613864e98f05862543557263e864Sebastien Hertz if ((pReq->options & JDWP::INVOKE_NONVIRTUAL) == 0 && pReq->receiver.Read() != nullptr) { 4094e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* actual_method = 4095e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier pReq->klass.Read()->FindVirtualMethodForVirtualOrInterface(m, image_pointer_size); 4096e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier if (actual_method != m) { 4097709b070044354d9f47641f273edacaeeb0240ab7David Sehr VLOG(jdwp) << "ExecuteMethod translated " << ArtMethod::PrettyMethod(m) 4098709b070044354d9f47641f273edacaeeb0240ab7David Sehr << " to " << ArtMethod::PrettyMethod(actual_method); 4099e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier m = actual_method; 410045651fde99f52546e71241bb0e8a10d16a9f216aElliott Hughes } 4101d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 4102709b070044354d9f47641f273edacaeeb0240ab7David Sehr VLOG(jdwp) << "ExecuteMethod " << ArtMethod::PrettyMethod(m) 41031558b577907b613864e98f05862543557263e864Sebastien Hertz << " receiver=" << pReq->receiver.Read() 4104d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz << " arg_count=" << pReq->arg_count; 4105e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier CHECK(m != nullptr); 4106d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 410733d6903e570daf8f3cf7c1f6ebd9a6dd22c7c23cRoland Levillain static_assert(sizeof(jvalue) == sizeof(uint64_t), "jvalue and uint64_t have different sizes."); 4108d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 4109cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // Invoke the method. 411039b6c24ce68cf05db0f82f454b4401cfb03d675fJeff Hao ScopedLocalRef<jobject> ref(soa.Env(), soa.AddLocalReference<jobject>(pReq->receiver.Read())); 411113b27842e88ccf1a42807c92daeb108e867dc4cdAndreas Gampe JValue result = InvokeWithJValues(soa, ref.get(), jni::EncodeArtMethod(m), 4112cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz reinterpret_cast<jvalue*>(pReq->arg_values.get())); 4113d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 4114cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // Prepare JDWP ids for the reply. 4115cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz JDWP::JdwpTag result_tag = BasicTagFromDescriptor(m->GetShorty()); 4116cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz const bool is_object_result = (result_tag == JDWP::JT_OBJECT); 4117064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao StackHandleScope<3> hs(soa.Self()); 41181558b577907b613864e98f05862543557263e864Sebastien Hertz Handle<mirror::Object> object_result = hs.NewHandle(is_object_result ? result.GetL() : nullptr); 41191558b577907b613864e98f05862543557263e864Sebastien Hertz Handle<mirror::Throwable> exception = hs.NewHandle(soa.Self()->GetException()); 41201558b577907b613864e98f05862543557263e864Sebastien Hertz soa.Self()->ClearException(); 4121cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz 4122cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz if (!IsDebuggerActive()) { 4123cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // The debugger detached: we must not re-suspend threads. We also don't need to fill the reply 4124cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // because it won't be sent either. 4125cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz return; 4126cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz } 4127cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz 4128cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz JDWP::ObjectId exceptionObjectId = gRegistry->Add(exception); 4129cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz uint64_t result_value = 0; 4130cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz if (exceptionObjectId != 0) { 41311558b577907b613864e98f05862543557263e864Sebastien Hertz VLOG(jdwp) << " JDWP invocation returning with exception=" << exception.Get() 41321558b577907b613864e98f05862543557263e864Sebastien Hertz << " " << exception->Dump(); 4133cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz result_value = 0; 41341558b577907b613864e98f05862543557263e864Sebastien Hertz } else if (is_object_result) { 4135cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz /* if no exception was thrown, examine object result more closely */ 41361558b577907b613864e98f05862543557263e864Sebastien Hertz JDWP::JdwpTag new_tag = TagFromObject(soa, object_result.Get()); 4137cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz if (new_tag != result_tag) { 4138cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz VLOG(jdwp) << " JDWP promoted result from " << result_tag << " to " << new_tag; 4139cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz result_tag = new_tag; 4140d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 4141d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 41421558b577907b613864e98f05862543557263e864Sebastien Hertz // Register the object in the registry and reference its ObjectId. This ensures 41431558b577907b613864e98f05862543557263e864Sebastien Hertz // GC safety and prevents from accessing stale reference if the object is moved. 4144cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz result_value = gRegistry->Add(object_result.Get()); 41451558b577907b613864e98f05862543557263e864Sebastien Hertz } else { 41461558b577907b613864e98f05862543557263e864Sebastien Hertz // Primitive result. 4147cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz DCHECK(IsPrimitiveTag(result_tag)); 4148cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz result_value = result.GetJ(); 4149cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz } 4150cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz const bool is_constructor = m->IsConstructor() && !m->IsStatic(); 4151cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz if (is_constructor) { 4152cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // If we invoked a constructor (which actually returns void), return the receiver, 4153cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // unless we threw, in which case we return null. 4154a3e1377f3f389a33f6a283796ea5cea1583911f3Sebastien Hertz DCHECK_EQ(JDWP::JT_VOID, result_tag); 4155cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz if (exceptionObjectId == 0) { 4156064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao if (m->GetDeclaringClass()->IsStringClass()) { 4157064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao // For string constructors, the new string is remapped to the receiver (stored in ref). 4158064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao Handle<mirror::Object> decoded_ref = hs.NewHandle(soa.Self()->DecodeJObject(ref.get())); 4159064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao result_value = gRegistry->Add(decoded_ref); 4160064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao result_tag = TagFromObject(soa, decoded_ref.Get()); 4161064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao } else { 4162064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao // TODO we could keep the receiver ObjectId in the DebugInvokeReq to avoid looking into the 4163064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao // object registry. 4164064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao result_value = GetObjectRegistry()->Add(pReq->receiver.Read()); 4165064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao result_tag = TagFromObject(soa, pReq->receiver.Read()); 4166064d24e921978a1d44f23aced69d2657d81e9af4Jeff Hao } 4167cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz } else { 4168cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz result_value = 0; 4169a3e1377f3f389a33f6a283796ea5cea1583911f3Sebastien Hertz result_tag = JDWP::JT_OBJECT; 4170cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz } 4171d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 4172d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes 4173cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // Suspend other threads if the invoke is not single-threaded. 4174cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz if ((pReq->options & JDWP::INVOKE_SINGLE_THREADED) == 0) { 4175f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier ScopedThreadSuspension sts(soa.Self(), kWaitingForDebuggerSuspension); 41768f95cf3cb5f715b1277de9cd7fade07ce4b230beHiroshi Yamauchi // Avoid a deadlock between GC and debugger where GC gets suspended during GC. b/25800335. 41778f95cf3cb5f715b1277de9cd7fade07ce4b230beHiroshi Yamauchi gc::ScopedGCCriticalSection gcs(soa.Self(), gc::kGcCauseDebugger, gc::kCollectorTypeDebugger); 4178cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz VLOG(jdwp) << " Suspending all threads"; 4179cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz Runtime::Current()->GetThreadList()->SuspendAllForDebugger(); 4180cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz } 4181cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz 4182cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz VLOG(jdwp) << " --> returned " << result_tag 4183cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz << StringPrintf(" %#" PRIx64 " (except=%#" PRIx64 ")", result_value, 4184cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz exceptionObjectId); 4185cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz 4186cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // Show detailed debug output. 4187cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz if (result_tag == JDWP::JT_STRING && exceptionObjectId == 0) { 4188cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz if (result_value != 0) { 4189cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz if (VLOG_IS_ON(jdwp)) { 4190cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz std::string result_string; 4191cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz JDWP::JdwpError error = Dbg::StringToUtf8(result_value, &result_string); 4192cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz CHECK_EQ(error, JDWP::ERR_NONE); 4193cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz VLOG(jdwp) << " string '" << result_string << "'"; 4194cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz } 4195cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz } else { 4196cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz VLOG(jdwp) << " string (null)"; 4197cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz } 4198cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz } 4199cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz 4200cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // Attach the reply to DebugInvokeReq so it can be sent to the debugger when the event thread 4201cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // is ready to suspend. 4202cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz BuildInvokeReply(pReq->reply, pReq->request_id, result_tag, result_value, exceptionObjectId); 4203cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz} 4204cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz 4205cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertzvoid Dbg::BuildInvokeReply(JDWP::ExpandBuf* pReply, uint32_t request_id, JDWP::JdwpTag result_tag, 4206cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz uint64_t result_value, JDWP::ObjectId exception) { 4207cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // Make room for the JDWP header since we do not know the size of the reply yet. 4208cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz JDWP::expandBufAddSpace(pReply, kJDWPHeaderLen); 4209cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz 4210cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz size_t width = GetTagWidth(result_tag); 4211cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz JDWP::expandBufAdd1(pReply, result_tag); 4212cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz if (width != 0) { 4213cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz WriteValue(pReply, width, result_value); 4214cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz } 4215cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz JDWP::expandBufAdd1(pReply, JDWP::JT_OBJECT); 4216cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz JDWP::expandBufAddObjectId(pReply, exception); 4217cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz 4218cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // Now we know the size, we can complete the JDWP header. 4219cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz uint8_t* buf = expandBufGetBuffer(pReply); 4220cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz JDWP::Set4BE(buf + kJDWPHeaderSizeOffset, expandBufGetLength(pReply)); 4221cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz JDWP::Set4BE(buf + kJDWPHeaderIdOffset, request_id); 4222cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz JDWP::Set1(buf + kJDWPHeaderFlagsOffset, kJDWPFlagReply); // flags 4223cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz JDWP::Set2BE(buf + kJDWPHeaderErrorCodeOffset, JDWP::ERR_NONE); 4224cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz} 4225cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz 4226cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertzvoid Dbg::FinishInvokeMethod(DebugInvokeReq* pReq) { 4227cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz CHECK_NE(Thread::Current(), GetDebugThread()) << "This must be called by the event thread"; 4228cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz 4229cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz JDWP::ExpandBuf* const pReply = pReq->reply; 4230cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz CHECK(pReply != nullptr) << "No reply attached to DebugInvokeReq"; 4231cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz 4232cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // We need to prevent other threads (including JDWP thread) from interacting with the debugger 4233cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // while we send the reply but are not yet suspended. The JDWP token will be released just before 4234cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // we suspend ourself again (see ThreadList::SuspendSelfForDebugger). 4235cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz gJdwpState->AcquireJdwpTokenForEvent(pReq->thread_id); 4236cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz 4237cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz // Send the reply unless the debugger detached before the completion of the method. 4238cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz if (IsDebuggerActive()) { 4239cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz const size_t replyDataLength = expandBufGetLength(pReply) - kJDWPHeaderLen; 4240cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz VLOG(jdwp) << StringPrintf("REPLY INVOKE id=0x%06x (length=%zu)", 4241cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz pReq->request_id, replyDataLength); 4242cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz 4243cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz gJdwpState->SendRequest(pReply); 4244cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz } else { 4245cbc5064ff05179b97b416f00ca579c55e38cd7d9Sebastien Hertz VLOG(jdwp) << "Not sending invoke reply because debugger detached"; 4246d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes } 4247872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 4248872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 4249d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes/* 42504b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes * "request" contains a full JDWP packet, possibly with multiple chunks. We 4251f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * need to process each, accumulate the replies, and ship the whole thing 4252f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * back. 4253f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * 4254f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * Returns "true" if we have a reply. The reply buffer is newly allocated, 4255f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * and includes the chunk type/length, followed by the data. 4256f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * 42573d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes * OLD-TODO: we currently assume that the request and reply include a single 4258f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * chunk. If this becomes inconvenient we will need to adapt. 4259f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes */ 4260c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersbool Dbg::DdmHandlePacket(JDWP::Request* request, uint8_t** pReplyBuf, int* pReplyLen) { 4261f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes Thread* self = Thread::Current(); 4262f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes JNIEnv* env = self->GetJniEnv(); 4263f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 4264c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers uint32_t type = request->ReadUnsigned32("type"); 4265c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers uint32_t length = request->ReadUnsigned32("length"); 42664b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes 42674b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes // Create a byte[] corresponding to 'request'. 4268c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers size_t request_length = request->size(); 42694b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes ScopedLocalRef<jbyteArray> dataArray(env, env->NewByteArray(request_length)); 4270c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (dataArray.get() == nullptr) { 42714b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes LOG(WARNING) << "byte[] allocation failed: " << request_length; 4272f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes env->ExceptionClear(); 4273f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes return false; 4274f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes } 4275c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers env->SetByteArrayRegion(dataArray.get(), 0, request_length, 4276c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers reinterpret_cast<const jbyte*>(request->data())); 4277c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers request->Skip(request_length); 4278f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 4279f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes // Run through and find all chunks. [Currently just find the first.] 42806a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes ScopedByteArrayRO contents(env, dataArray.get()); 42814b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes if (length != request_length) { 4282ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers LOG(WARNING) << StringPrintf("bad chunk found (len=%u pktLen=%zd)", length, request_length); 4283f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes return false; 4284f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes } 4285f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 4286f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes // Call "private static Chunk dispatch(int type, byte[] data, int offset, int length)". 4287eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes ScopedLocalRef<jobject> chunk(env, env->CallStaticObjectMethod(WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer, 4288eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer_dispatch, 42894b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes type, dataArray.get(), 0, length)); 4290f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes if (env->ExceptionCheck()) { 4291f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes LOG(INFO) << StringPrintf("Exception thrown by dispatcher for 0x%08x", type); 4292f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes env->ExceptionDescribe(); 4293f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes env->ExceptionClear(); 4294f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes return false; 4295f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes } 4296f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 4297c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (chunk.get() == nullptr) { 4298f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes return false; 4299f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes } 4300f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 4301f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes /* 4302f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * Pull the pieces out of the chunk. We copy the results into a 4303f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * newly-allocated buffer that the caller can free. We don't want to 4304f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * continue using the Chunk object because nothing has a reference to it. 4305f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * 4306f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * We could avoid this by returning type/data/offset/length and having 4307f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * the caller be aware of the object lifetime issues, but that 430881ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes * integrates the JDWP code more tightly into the rest of the runtime, and doesn't work 4309f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * if we have responses for multiple chunks. 4310f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * 4311f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * So we're pretty much stuck with copying data around multiple times. 4312f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes */ 4313eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes ScopedLocalRef<jbyteArray> replyData(env, reinterpret_cast<jbyteArray>(env->GetObjectField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_data))); 43144b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes jint offset = env->GetIntField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_offset); 4315eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes length = env->GetIntField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_length); 4316eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes type = env->GetIntField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_type); 4317f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 43184dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << StringPrintf("DDM reply: type=0x%08x data=%p offset=%d length=%d", type, replyData.get(), offset, length); 4319c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (length == 0 || replyData.get() == nullptr) { 4320f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes return false; 4321f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes } 4322f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 43234b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes const int kChunkHdrLen = 8; 4324f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes uint8_t* reply = new uint8_t[length + kChunkHdrLen]; 4325c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (reply == nullptr) { 4326f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes LOG(WARNING) << "malloc failed: " << (length + kChunkHdrLen); 4327f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes return false; 4328f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes } 4329f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes JDWP::Set4BE(reply + 0, type); 4330f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes JDWP::Set4BE(reply + 4, length); 43316a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes env->GetByteArrayRegion(replyData.get(), offset, length, reinterpret_cast<jbyte*>(reply + kChunkHdrLen)); 4332f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 4333f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes *pReplyBuf = reply; 4334f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes *pReplyLen = length + kChunkHdrLen; 4335f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 43364b9702c6912c6f8745a77f5b5af56e7fe196e7c2Elliott Hughes VLOG(jdwp) << StringPrintf("dvmHandleDdm returning type=%.4s %p len=%d", reinterpret_cast<char*>(reply), reply, length); 4337f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes return true; 4338872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 4339872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 4340a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughesvoid Dbg::DdmBroadcast(bool connect) { 43414dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << "Broadcasting DDM " << (connect ? "connect" : "disconnect") << "..."; 434247fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 434347fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes Thread* self = Thread::Current(); 434450b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers if (self->GetState() != kRunnable) { 434550b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers LOG(ERROR) << "DDM broadcast in thread state " << self->GetState(); 434650b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers /* try anyway? */ 434747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes } 434847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 434947fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes JNIEnv* env = self->GetJniEnv(); 435047fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes jint event = connect ? 1 /*DdmServer.CONNECTED*/ : 2 /*DdmServer.DISCONNECTED*/; 4351eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes env->CallStaticVoidMethod(WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer, 4352eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer_broadcast, 4353eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes event); 435447fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes if (env->ExceptionCheck()) { 435547fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes LOG(ERROR) << "DdmServer.broadcast " << event << " failed"; 435647fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes env->ExceptionDescribe(); 435747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes env->ExceptionClear(); 435847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes } 435947fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes} 436047fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 4361872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::DdmConnected() { 4362a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes Dbg::DdmBroadcast(true); 4363872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 4364872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 4365872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid Dbg::DdmDisconnected() { 4366a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes Dbg::DdmBroadcast(false); 436747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes gDdmThreadNotification = false; 436847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes} 436947fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 437047fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes/* 43718218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes * Send a notification when a thread starts, stops, or changes its name. 437247fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes * 437347fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes * Because we broadcast the full set of threads when the notifications are 437447fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes * first enabled, it's possible for "thread" to be actively executing. 437547fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes */ 43768218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughesvoid Dbg::DdmSendThreadNotification(Thread* t, uint32_t type) { 437747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes if (!gDdmThreadNotification) { 437847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes return; 437947fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes } 438047fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 43818218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes if (type == CHUNK_TYPE("THDE")) { 43828218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes uint8_t buf[4]; 4383d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers JDWP::Set4BE(&buf[0], t->GetThreadId()); 43848218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes Dbg::DdmSendChunk(CHUNK_TYPE("THDE"), 4, buf); 43858218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes } else { 43868218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes CHECK(type == CHUNK_TYPE("THCR") || type == CHUNK_TYPE("THNM")) << type; 438700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccessUnchecked soa(Thread::Current()); 4388eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<1> hs(soa.Self()); 438908883debd927d18c9ecf66683a2a11aa98165656Andreas Gampe Handle<mirror::String> name(hs.NewHandle(t->GetThreadName())); 4390fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe size_t char_count = (name != nullptr) ? name->GetLength() : 0; 4391fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe const jchar* chars = (name != nullptr) ? name->GetValue() : nullptr; 4392fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe bool is_compressed = (name != nullptr) ? name->IsCompressed() : false; 439347fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 439421f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes std::vector<uint8_t> bytes; 4395d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers JDWP::Append4BE(bytes, t->GetThreadId()); 43963aaa37bba53d6df0265793de48b4b0b57327e57ajessicahandojo if (is_compressed) { 43973aaa37bba53d6df0265793de48b4b0b57327e57ajessicahandojo const uint8_t* chars_compressed = name->GetValueCompressed(); 43983aaa37bba53d6df0265793de48b4b0b57327e57ajessicahandojo JDWP::AppendUtf16CompressedBE(bytes, chars_compressed, char_count); 43993aaa37bba53d6df0265793de48b4b0b57327e57ajessicahandojo } else { 44003aaa37bba53d6df0265793de48b4b0b57327e57ajessicahandojo JDWP::AppendUtf16BE(bytes, chars, char_count); 44013aaa37bba53d6df0265793de48b4b0b57327e57ajessicahandojo } 440221f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes CHECK_EQ(bytes.size(), char_count*2 + sizeof(uint32_t)*2); 440321f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes Dbg::DdmSendChunk(type, bytes); 440447fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes } 440547fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes} 440647fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 440747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughesvoid Dbg::DdmSetThreadNotification(bool enable) { 440800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Enable/disable thread notifications. 440947fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes gDdmThreadNotification = enable; 441047fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes if (enable) { 441100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Suspend the VM then post thread start notifications for all threads. Threads attaching will 441200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // see a suspension in progress and block until that ends. They then post their own start 441300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // notification. 441400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers SuspendVM(); 441500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers std::list<Thread*> threads; 441650b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers Thread* self = Thread::Current(); 441700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers { 441850b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu(self, *Locks::thread_list_lock_); 441900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers threads = Runtime::Current()->GetThreadList()->GetList(); 442000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 442100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers { 442250b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers ScopedObjectAccess soa(self); 442302e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier for (Thread* thread : threads) { 442402e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier Dbg::DdmSendThreadNotification(thread, CHUNK_TYPE("THCR")); 442500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 442600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 442700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ResumeVM(); 442847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes } 442947fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes} 443047fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 4431a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughesvoid Dbg::PostThreadStartOrStop(Thread* t, uint32_t type) { 4432c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes if (IsDebuggerActive()) { 44336995c60cd6657c10811055c42661a55b10b47cefSebastien Hertz gJdwpState->PostThreadChange(t, type == CHUNK_TYPE("THCR")); 443447fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes } 44358218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughes Dbg::DdmSendThreadNotification(t, type); 443647fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes} 443747fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 443847fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughesvoid Dbg::PostThreadStart(Thread* t) { 4439a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes Dbg::PostThreadStartOrStop(t, CHUNK_TYPE("THCR")); 444047fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes} 444147fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes 444247fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughesvoid Dbg::PostThreadDeath(Thread* t) { 4443a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes Dbg::PostThreadStartOrStop(t, CHUNK_TYPE("THDE")); 4444872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 4445872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 44468218847294600bbfcdc041a46c2b579b6e70cf3bElliott Hughesvoid Dbg::DdmSendChunk(uint32_t type, size_t byte_count, const uint8_t* buf) { 4447c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers CHECK(buf != nullptr); 44483bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes iovec vec[1]; 44493bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes vec[0].iov_base = reinterpret_cast<void*>(const_cast<uint8_t*>(buf)); 44503bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes vec[0].iov_len = byte_count; 44513bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes Dbg::DdmSendChunkV(type, vec, 1); 4452872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 4453872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 445421f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughesvoid Dbg::DdmSendChunk(uint32_t type, const std::vector<uint8_t>& bytes) { 445521f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes DdmSendChunk(type, bytes.size(), &bytes[0]); 445621f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes} 445721f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes 4458f52935278fca8c7aa220543eef4544e3d1105d91Brian Carlstromvoid Dbg::DdmSendChunkV(uint32_t type, const iovec* iov, int iov_count) { 4459c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (gJdwpState == nullptr) { 44604dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << "Debugger thread not active, ignoring DDM send: " << type; 44613bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } else { 4462cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes gJdwpState->DdmSendChunkV(type, iov, iov_count); 44633bb81563481d02b5a6349b8ed918392454e761d8Elliott Hughes } 4464872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 4465872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 4466ad466adf38db74a9840659626858196091151a64Mathieu ChartierJDWP::JdwpState* Dbg::GetJdwpState() { 4467ad466adf38db74a9840659626858196091151a64Mathieu Chartier return gJdwpState; 4468ad466adf38db74a9840659626858196091151a64Mathieu Chartier} 4469ad466adf38db74a9840659626858196091151a64Mathieu Chartier 4470767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesint Dbg::DdmHandleHpifChunk(HpifWhen when) { 4471767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes if (when == HPIF_WHEN_NOW) { 44727162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes DdmSendHeapInfo(when); 4473767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes return true; 4474767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } 4475767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 4476767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes if (when != HPIF_WHEN_NEVER && when != HPIF_WHEN_NEXT_GC && when != HPIF_WHEN_EVERY_GC) { 4477767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes LOG(ERROR) << "invalid HpifWhen value: " << static_cast<int>(when); 4478767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes return false; 4479767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } 4480767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 4481767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes gDdmHpifWhen = when; 4482767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes return true; 4483767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes} 4484767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 4485767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughesbool Dbg::DdmHandleHpsgNhsgChunk(Dbg::HpsgWhen when, Dbg::HpsgWhat what, bool native) { 4486767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes if (when != HPSG_WHEN_NEVER && when != HPSG_WHEN_EVERY_GC) { 4487767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes LOG(ERROR) << "invalid HpsgWhen value: " << static_cast<int>(when); 4488767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes return false; 4489767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } 4490767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 4491767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes if (what != HPSG_WHAT_MERGED_OBJECTS && what != HPSG_WHAT_DISTINCT_OBJECTS) { 4492767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes LOG(ERROR) << "invalid HpsgWhat value: " << static_cast<int>(what); 4493767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes return false; 4494767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } 4495767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 4496767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes if (native) { 4497767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes gDdmNhsgWhen = when; 4498767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes gDdmNhsgWhat = what; 4499767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } else { 4500767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes gDdmHpsgWhen = when; 4501767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes gDdmHpsgWhat = what; 4502767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } 4503767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes return true; 4504767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes} 4505767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 45067162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughesvoid Dbg::DdmSendHeapInfo(HpifWhen reason) { 45077162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes // If there's a one-shot 'when', reset it. 45087162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes if (reason == gDdmHpifWhen) { 45097162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes if (gDdmHpifWhen == HPIF_WHEN_NEXT_GC) { 45107162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes gDdmHpifWhen = HPIF_WHEN_NEVER; 45117162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes } 45127162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes } 45137162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes 45147162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes /* 45157162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * Chunk HPIF (client --> server) 45167162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * 45177162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * Heap Info. General information about the heap, 45187162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * suitable for a summary display. 45197162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * 45207162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * [u4]: number of heaps 45217162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * 45227162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * For each heap: 45237162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * [u4]: heap ID 45247162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * [u8]: timestamp in ms since Unix epoch 45257162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * [u1]: capture reason (same as 'when' value from server) 45267162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * [u4]: max heap size in bytes (-Xmx) 45277162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * [u4]: current heap size in bytes 45287162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * [u4]: current number of bytes allocated 45297162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes * [u4]: current number of objects allocated 45307162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes */ 45317162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes uint8_t heap_count = 1; 45321d54e73444e017d3a65234e0f193846f3e27472bIan Rogers gc::Heap* heap = Runtime::Current()->GetHeap(); 453321f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes std::vector<uint8_t> bytes; 4534545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes JDWP::Append4BE(bytes, heap_count); 45357934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom JDWP::Append4BE(bytes, 1); // Heap id (bogus; we only have one heap). 4536545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes JDWP::Append8BE(bytes, MilliTime()); 4537545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes JDWP::Append1BE(bytes, reason); 45387934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom JDWP::Append4BE(bytes, heap->GetMaxMemory()); // Max allowed heap size in bytes. 45397934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom JDWP::Append4BE(bytes, heap->GetTotalMemory()); // Current heap size in bytes. 4540b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes JDWP::Append4BE(bytes, heap->GetBytesAllocated()); 4541b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes JDWP::Append4BE(bytes, heap->GetObjectsAllocated()); 454221f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes CHECK_EQ(bytes.size(), 4U + (heap_count * (4 + 8 + 1 + 4 + 4 + 4 + 4))); 454321f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes Dbg::DdmSendChunk(CHUNK_TYPE("HPIF"), bytes); 4544767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes} 4545767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 45466a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughesenum HpsgSolidity { 45476a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes SOLIDITY_FREE = 0, 45486a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes SOLIDITY_HARD = 1, 45496a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes SOLIDITY_SOFT = 2, 45506a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes SOLIDITY_WEAK = 3, 45516a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes SOLIDITY_PHANTOM = 4, 45526a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes SOLIDITY_FINALIZABLE = 5, 45536a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes SOLIDITY_SWEEP = 6, 45546a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes}; 45556a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 45566a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughesenum HpsgKind { 45576a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes KIND_OBJECT = 0, 45586a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes KIND_CLASS_OBJECT = 1, 45596a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes KIND_ARRAY_1 = 2, 45606a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes KIND_ARRAY_2 = 3, 45616a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes KIND_ARRAY_4 = 4, 45626a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes KIND_ARRAY_8 = 5, 45636a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes KIND_UNKNOWN = 6, 45646a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes KIND_NATIVE = 7, 45656a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes}; 45666a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 45676a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes#define HPSG_PARTIAL (1<<7) 45686a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes#define HPSG_STATE(solidity, kind) ((uint8_t)((((kind) & 0x7) << 3) | ((solidity) & 0x7))) 45696a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 457030fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogersclass HeapChunkContext { 457130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers public: 45726a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // Maximum chunk size. Obtain this from the formula: 45736a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // (((maximum_heap_size / ALLOCATION_UNIT_SIZE) + 255) / 256) * 2 45746a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes HeapChunkContext(bool merge, bool native) 457530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers : buf_(16384 - 16), 457630fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers type_(0), 457736dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier chunk_overhead_(0) { 45786a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes Reset(); 45796a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes if (native) { 458030fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers type_ = CHUNK_TYPE("NHSG"); 45816a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } else { 458230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers type_ = merge ? CHUNK_TYPE("HPSG") : CHUNK_TYPE("HPSO"); 45836a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 45846a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 45856a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 45866a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes ~HeapChunkContext() { 458730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers if (p_ > &buf_[0]) { 45886a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes Flush(); 45896a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 45906a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 45916a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 459236dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier void SetChunkOverhead(size_t chunk_overhead) { 459336dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier chunk_overhead_ = chunk_overhead; 459436dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier } 459536dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier 459636dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier void ResetStartOfNextChunk() { 459736dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier startOfNextMemoryChunk_ = nullptr; 459836dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier } 459936dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier 46006a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes void EnsureHeader(const void* chunk_ptr) { 460130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers if (!needHeader_) { 46026a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes return; 46036a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 46046a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 46056a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // Start a new HPSx chunk. 46067934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom JDWP::Write4BE(&p_, 1); // Heap id (bogus; we only have one heap). 46077934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom JDWP::Write1BE(&p_, 8); // Size of allocation unit, in bytes. 46086a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 46097934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom JDWP::Write4BE(&p_, reinterpret_cast<uintptr_t>(chunk_ptr)); // virtual address of segment start. 46107934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom JDWP::Write4BE(&p_, 0); // offset of this piece (relative to the virtual address). 46116a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // [u4]: length of piece, in allocation units 46126a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // We won't know this until we're done, so save the offset and stuff in a dummy value. 461330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers pieceLenField_ = p_; 461430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers JDWP::Write4BE(&p_, 0x55555555); 461530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers needHeader_ = false; 46166a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 46176a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 4618bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe void Flush() REQUIRES_SHARED(Locks::mutator_lock_) { 4619c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (pieceLenField_ == nullptr) { 4620d636b0623307a379e255a9aaa682c12a2acc3a92Ian Rogers // Flush immediately post Reset (maybe back-to-back Flush). Ignore. 4621d636b0623307a379e255a9aaa682c12a2acc3a92Ian Rogers CHECK(needHeader_); 4622d636b0623307a379e255a9aaa682c12a2acc3a92Ian Rogers return; 4623d636b0623307a379e255a9aaa682c12a2acc3a92Ian Rogers } 46246a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // Patch the "length of piece" field. 462530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers CHECK_LE(&buf_[0], pieceLenField_); 462630fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers CHECK_LE(pieceLenField_, p_); 462730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers JDWP::Set4BE(pieceLenField_, totalAllocationUnits_); 46286a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 462930fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers Dbg::DdmSendChunk(type_, p_ - &buf_[0], &buf_[0]); 46306a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes Reset(); 46316a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 46326a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 4633bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier static void HeapChunkJavaCallback(void* start, void* end, size_t used_bytes, void* arg) 4634bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::heap_bitmap_lock_, 4635b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers Locks::mutator_lock_) { 4636bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier reinterpret_cast<HeapChunkContext*>(arg)->HeapChunkJavaCallback(start, end, used_bytes); 4637bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier } 4638bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier 4639bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier static void HeapChunkNativeCallback(void* start, void* end, size_t used_bytes, void* arg) 4640bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 4641bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier reinterpret_cast<HeapChunkContext*>(arg)->HeapChunkNativeCallback(start, end, used_bytes); 4642a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 4643a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 46446a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes private: 4645a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes enum { ALLOCATION_UNIT_SIZE = 8 }; 4646a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 46476a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes void Reset() { 464830fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers p_ = &buf_[0]; 464936dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier ResetStartOfNextChunk(); 465030fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers totalAllocationUnits_ = 0; 465130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers needHeader_ = true; 4652c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers pieceLenField_ = nullptr; 46536a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 46546a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 4655bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier bool IsNative() const { 4656bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier return type_ == CHUNK_TYPE("NHSG"); 4657bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier } 4658bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier 4659bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier // Returns true if the object is not an empty chunk. 4660bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe bool ProcessRecord(void* start, size_t used_bytes) REQUIRES_SHARED(Locks::mutator_lock_) { 466130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers // Note: heap call backs cannot manipulate the heap upon which they are crawling, care is taken 466230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers // in the following code not to allocate memory, by ensuring buf_ is of the correct size 466315bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers if (used_bytes == 0) { 4664bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier if (start == nullptr) { 4665bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier // Reset for start of new heap. 4666bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier startOfNextMemoryChunk_ = nullptr; 4667bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier Flush(); 4668bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier } 4669bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier // Only process in use memory so that free region information 4670bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier // also includes dlmalloc book keeping. 4671bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier return false; 4672a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 4673c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (startOfNextMemoryChunk_ != nullptr) { 4674bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier // Transmit any pending free memory. Native free memory of over kMaxFreeLen could be because 4675bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier // of the use of mmaps, so don't report. If not free memory then start a new segment. 4676bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier bool flush = true; 4677bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier if (start > startOfNextMemoryChunk_) { 4678bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier const size_t kMaxFreeLen = 2 * kPageSize; 4679bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier void* free_start = startOfNextMemoryChunk_; 4680bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier void* free_end = start; 4681bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier const size_t free_len = 4682bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier reinterpret_cast<uintptr_t>(free_end) - reinterpret_cast<uintptr_t>(free_start); 4683bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier if (!IsNative() || free_len < kMaxFreeLen) { 4684bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier AppendChunk(HPSG_STATE(SOLIDITY_FREE, 0), free_start, free_len, IsNative()); 4685bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier flush = false; 468615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers } 4687bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier } 4688bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier if (flush) { 4689bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier startOfNextMemoryChunk_ = nullptr; 4690bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier Flush(); 4691bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier } 469215bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers } 4693bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier return true; 4694bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier } 4695bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier 4696bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier void HeapChunkNativeCallback(void* start, void* /*end*/, size_t used_bytes) 4697bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 4698bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier if (ProcessRecord(start, used_bytes)) { 4699bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier uint8_t state = ExamineNativeObject(start); 4700bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier AppendChunk(state, start, used_bytes + chunk_overhead_, true /*is_native*/); 4701bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier startOfNextMemoryChunk_ = reinterpret_cast<char*>(start) + used_bytes + chunk_overhead_; 4702bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier } 4703bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier } 4704a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 4705bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier void HeapChunkJavaCallback(void* start, void* /*end*/, size_t used_bytes) 4706bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) { 4707bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier if (ProcessRecord(start, used_bytes)) { 4708bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier // Determine the type of this chunk. 4709bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier // OLD-TODO: if context.merge, see if this chunk is different from the last chunk. 4710bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier // If it's the same, we should combine them. 4711bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier uint8_t state = ExamineJavaObject(reinterpret_cast<mirror::Object*>(start)); 4712bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier AppendChunk(state, start, used_bytes + chunk_overhead_, false /*is_native*/); 4713bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier startOfNextMemoryChunk_ = reinterpret_cast<char*>(start) + used_bytes + chunk_overhead_; 4714bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier } 471515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers } 471615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers 4717bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier void AppendChunk(uint8_t state, void* ptr, size_t length, bool is_native) 4718bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 471915bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers // Make sure there's enough room left in the buffer. 472015bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers // We need to use two bytes for every fractional 256 allocation units used by the chunk plus 472115bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers // 17 bytes for any header. 4722bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier const size_t needed = ((RoundUp(length / ALLOCATION_UNIT_SIZE, 256) / 256) * 2) + 17; 4723bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier size_t byte_left = &buf_.back() - p_; 4724bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier if (byte_left < needed) { 4725bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier if (is_native) { 47267522c741d9660a56da2dd6a8e20b8cdf01a6c333Pavel Vyssotski // Cannot trigger memory allocation while walking native heap. 47277522c741d9660a56da2dd6a8e20b8cdf01a6c333Pavel Vyssotski return; 47287522c741d9660a56da2dd6a8e20b8cdf01a6c333Pavel Vyssotski } 472915bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers Flush(); 473015bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers } 4731a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes 4732bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier byte_left = &buf_.back() - p_; 4733bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier if (byte_left < needed) { 473415bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers LOG(WARNING) << "Chunk is too big to transmit (chunk_len=" << length << ", " 473515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers << needed << " bytes)"; 473615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers return; 473715bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers } 473815bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers EnsureHeader(ptr); 4739a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // Write out the chunk description. 474015bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers length /= ALLOCATION_UNIT_SIZE; // Convert to allocation units. 474115bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers totalAllocationUnits_ += length; 474215bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers while (length > 256) { 474330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers *p_++ = state | HPSG_PARTIAL; 474430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers *p_++ = 255; // length - 1 474515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers length -= 256; 4746a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 474730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers *p_++ = state; 474815bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers *p_++ = length - 1; 47496a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 47506a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 4751bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe uint8_t ExamineNativeObject(const void* p) REQUIRES_SHARED(Locks::mutator_lock_) { 4752bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier return p == nullptr ? HPSG_STATE(SOLIDITY_FREE, 0) : HPSG_STATE(SOLIDITY_HARD, KIND_NATIVE); 4753bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier } 4754bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier 4755bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier uint8_t ExamineJavaObject(mirror::Object* o) 4756bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) { 4757c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (o == nullptr) { 4758a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return HPSG_STATE(SOLIDITY_FREE, 0); 4759a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 4760a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // It's an allocated chunk. Figure out what it is. 4761bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier gc::Heap* heap = Runtime::Current()->GetHeap(); 4762bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier if (!heap->IsLiveObjectLocked(o)) { 4763bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier LOG(ERROR) << "Invalid object in managed heap: " << o; 476415bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers return HPSG_STATE(SOLIDITY_HARD, KIND_NATIVE); 476500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 47662dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = o->GetClass(); 4767c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (c == nullptr) { 4768a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes // The object was probably just created but hasn't been initialized yet. 4769a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT); 4770a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 4771bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier if (!heap->IsValidObjectAddress(c)) { 477215bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers LOG(ERROR) << "Invalid class for managed heap object: " << o << " " << c; 4773a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return HPSG_STATE(SOLIDITY_HARD, KIND_UNKNOWN); 4774a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 4775f26e1b355333cbb5b064da3b4bbf2dc450a5eb40Mathieu Chartier if (c->GetClass() == nullptr) { 4776f26e1b355333cbb5b064da3b4bbf2dc450a5eb40Mathieu Chartier LOG(ERROR) << "Null class of class " << c << " for object " << o; 4777f26e1b355333cbb5b064da3b4bbf2dc450a5eb40Mathieu Chartier return HPSG_STATE(SOLIDITY_HARD, KIND_UNKNOWN); 4778f26e1b355333cbb5b064da3b4bbf2dc450a5eb40Mathieu Chartier } 4779a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes if (c->IsClassClass()) { 4780a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return HPSG_STATE(SOLIDITY_HARD, KIND_CLASS_OBJECT); 47816a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 4782a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes if (c->IsArrayClass()) { 4783a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes switch (c->GetComponentSize()) { 4784a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes case 1: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_1); 4785a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes case 2: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_2); 4786a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes case 4: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_4); 4787a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes case 8: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_8); 4788a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 47896a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 4790a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes return HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT); 47916a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 47926a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 479330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers std::vector<uint8_t> buf_; 479430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers uint8_t* p_; 479530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers uint8_t* pieceLenField_; 479615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers void* startOfNextMemoryChunk_; 479730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers size_t totalAllocationUnits_; 479830fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers uint32_t type_; 479930fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers bool needHeader_; 480036dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier size_t chunk_overhead_; 480130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers 4802a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes DISALLOW_COPY_AND_ASSIGN(HeapChunkContext); 4803a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes}; 48046a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 480536dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartierstatic void BumpPointerSpaceCallback(mirror::Object* obj, void* arg) 4806bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) { 480736dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier const size_t size = RoundUp(obj->SizeOf(), kObjectAlignment); 4808bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier HeapChunkContext::HeapChunkJavaCallback( 480936dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier obj, reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(obj) + size), size, arg); 481036dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier} 481136dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier 48126a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughesvoid Dbg::DdmSendHeapSegments(bool native) { 4813bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier Dbg::HpsgWhen when = native ? gDdmNhsgWhen : gDdmHpsgWhen; 4814bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier Dbg::HpsgWhat what = native ? gDdmNhsgWhat : gDdmHpsgWhat; 48156a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes if (when == HPSG_WHEN_NEVER) { 48166a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes return; 48176a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes } 48186a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // Figure out what kind of chunks we'll be sending. 4819bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier CHECK(what == HPSG_WHAT_MERGED_OBJECTS || what == HPSG_WHAT_DISTINCT_OBJECTS) 4820bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier << static_cast<int>(what); 48216a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 48226a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // First, send a heap start chunk. 48236a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes uint8_t heap_id[4]; 48247934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom JDWP::Set4BE(&heap_id[0], 1); // Heap id (bogus; we only have one heap). 48256a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes Dbg::DdmSendChunk(native ? CHUNK_TYPE("NHST") : CHUNK_TYPE("HPST"), sizeof(heap_id), heap_id); 4826cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi Thread* self = Thread::Current(); 4827cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi Locks::mutator_lock_->AssertSharedHeld(self); 4828cf58d4adf461eb9b8e84baa8019054c88cd8acc6Hiroshi Yamauchi 48296a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // Send a series of heap segment chunks. 4830bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier HeapChunkContext context(what == HPSG_WHAT_MERGED_OBJECTS, native); 4831a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes if (native) { 4832e6465bc8a52cfa3995b4072810cdb7ab397a7793Dimitry Ivanov UNIMPLEMENTED(WARNING) << "Native heap inspection is not supported"; 4833a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } else { 48341d54e73444e017d3a65234e0f193846f3e27472bIan Rogers gc::Heap* heap = Runtime::Current()->GetHeap(); 483536dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier for (const auto& space : heap->GetContinuousSpaces()) { 483636dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier if (space->IsDlMallocSpace()) { 48374c69d7f4df78d20c631abc5f70b811a9944854d3Mathieu Chartier ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_); 483836dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier // dlmalloc's chunk header is 2 * sizeof(size_t), but if the previous chunk is in use for an 483936dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier // allocation then the first sizeof(size_t) may belong to it. 484036dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier context.SetChunkOverhead(sizeof(size_t)); 4841bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier space->AsDlMallocSpace()->Walk(HeapChunkContext::HeapChunkJavaCallback, &context); 484236dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier } else if (space->IsRosAllocSpace()) { 484336dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier context.SetChunkOverhead(0); 48444c69d7f4df78d20c631abc5f70b811a9944854d3Mathieu Chartier // Need to acquire the mutator lock before the heap bitmap lock with exclusive access since 48454c69d7f4df78d20c631abc5f70b811a9944854d3Mathieu Chartier // RosAlloc's internal logic doesn't know to release and reacquire the heap bitmap lock. 4846f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier ScopedThreadSuspension sts(self, kSuspended); 48474f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier ScopedSuspendAll ssa(__FUNCTION__); 48484f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_); 48494f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier space->AsRosAllocSpace()->Walk(HeapChunkContext::HeapChunkJavaCallback, &context); 485036dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier } else if (space->IsBumpPointerSpace()) { 48514c69d7f4df78d20c631abc5f70b811a9944854d3Mathieu Chartier ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_); 485236dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier context.SetChunkOverhead(0); 485336dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier space->AsBumpPointerSpace()->Walk(BumpPointerSpaceCallback, &context); 4854bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier HeapChunkContext::HeapChunkJavaCallback(nullptr, nullptr, 0, &context); 48552cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi } else if (space->IsRegionSpace()) { 48562cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi heap->IncrementDisableMovingGC(self); 4857f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier { 4858f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier ScopedThreadSuspension sts(self, kSuspended); 48594f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier ScopedSuspendAll ssa(__FUNCTION__); 4860f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_); 4861f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier context.SetChunkOverhead(0); 4862f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier space->AsRegionSpace()->Walk(BumpPointerSpaceCallback, &context); 4863f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier HeapChunkContext::HeapChunkJavaCallback(nullptr, nullptr, 0, &context); 4864f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier } 48652cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi heap->DecrementDisableMovingGC(self); 486636dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier } else { 486736dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier UNIMPLEMENTED(WARNING) << "Not counting objects in space " << *space; 4868b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier } 486936dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier context.ResetStartOfNextChunk(); 4870b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier } 48714c69d7f4df78d20c631abc5f70b811a9944854d3Mathieu Chartier ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_); 4872e0f0cb3d855cb5e926452b5e1ec8457adc4e454eMathieu Chartier // Walk the large objects, these are not in the AllocSpace. 487336dab3607e77505ce139eacef1c62a1c4bc4affdMathieu Chartier context.SetChunkOverhead(0); 4874bc689b7cefce2dd357abf25b82e5fcd690e27706Mathieu Chartier heap->GetLargeObjectsSpace()->Walk(HeapChunkContext::HeapChunkJavaCallback, &context); 4875a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes } 48766a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes 48776a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes // Finally, send a heap end chunk. 48786a5bd495ff2f614f1495f652c86f3902d3bde537Elliott Hughes Dbg::DdmSendChunk(native ? CHUNK_TYPE("NHEN") : CHUNK_TYPE("HPEN"), sizeof(heap_id), heap_id); 4879767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes} 4880767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 4881306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstromvoid Dbg::SetAllocTrackingEnabled(bool enable) { 48828c2ff641294715864013737fdec57cdfd410270cMan Cao gc::AllocRecordObjectMap::SetAllocTrackingEnabled(enable); 4883545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes} 4884545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 4885545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughesvoid Dbg::DumpRecentAllocations() { 488600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 4887306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom MutexLock mu(soa.Self(), *Locks::alloc_tracker_lock_); 48888c2ff641294715864013737fdec57cdfd410270cMan Cao if (!Runtime::Current()->GetHeap()->IsAllocTrackingEnabled()) { 4889545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes LOG(INFO) << "Not recording tracked allocations"; 4890545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes return; 4891545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 48928c2ff641294715864013737fdec57cdfd410270cMan Cao gc::AllocRecordObjectMap* records = Runtime::Current()->GetHeap()->GetAllocationRecords(); 48938c2ff641294715864013737fdec57cdfd410270cMan Cao CHECK(records != nullptr); 4894545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 48951ed11b9ad5512cf464cb1686640df53201fa5297Man Cao const uint16_t capped_count = CappedAllocRecordCount(records->GetRecentAllocationSize()); 4896306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom uint16_t count = capped_count; 4897545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 48988c2ff641294715864013737fdec57cdfd410270cMan Cao LOG(INFO) << "Tracked allocations, (count=" << count << ")"; 48998c2ff641294715864013737fdec57cdfd410270cMan Cao for (auto it = records->RBegin(), end = records->REnd(); 49008c2ff641294715864013737fdec57cdfd410270cMan Cao count > 0 && it != end; count--, it++) { 4901458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier const gc::AllocRecord* record = &it->second; 4902545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 49038c2ff641294715864013737fdec57cdfd410270cMan Cao LOG(INFO) << StringPrintf(" Thread %-2d %6zd bytes ", record->GetTid(), record->ByteCount()) 4904709b070044354d9f47641f273edacaeeb0240ab7David Sehr << mirror::Class::PrettyClass(record->GetClass()); 4905545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 49068c2ff641294715864013737fdec57cdfd410270cMan Cao for (size_t stack_frame = 0, depth = record->GetDepth(); stack_frame < depth; ++stack_frame) { 49078c2ff641294715864013737fdec57cdfd410270cMan Cao const gc::AllocRecordStackTraceElement& stack_element = record->StackElement(stack_frame); 49088c2ff641294715864013737fdec57cdfd410270cMan Cao ArtMethod* m = stack_element.GetMethod(); 4909709b070044354d9f47641f273edacaeeb0240ab7David Sehr LOG(INFO) << " " << ArtMethod::PrettyMethod(m) << " line " 4910709b070044354d9f47641f273edacaeeb0240ab7David Sehr << stack_element.ComputeLineNumber(); 4911545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 4912545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 4913545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes // pause periodically to help logcat catch up 4914545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes if ((count % 5) == 0) { 4915545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes usleep(40000); 4916545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 4917545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 4918545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes} 4919545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 4920545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughesclass StringTable { 4921545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes public: 4922545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes StringTable() { 4923545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 4924545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 49254345c46b8a927cf13d9bbe38f8cf0593f5de181bMathieu Chartier void Add(const std::string& str) { 49264345c46b8a927cf13d9bbe38f8cf0593f5de181bMathieu Chartier table_.insert(str); 49274345c46b8a927cf13d9bbe38f8cf0593f5de181bMathieu Chartier } 49284345c46b8a927cf13d9bbe38f8cf0593f5de181bMathieu Chartier 49294345c46b8a927cf13d9bbe38f8cf0593f5de181bMathieu Chartier void Add(const char* str) { 49304345c46b8a927cf13d9bbe38f8cf0593f5de181bMathieu Chartier table_.insert(str); 4931545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 4932545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 4933a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes size_t IndexOf(const char* s) const { 493402e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier auto it = table_.find(s); 4935a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes if (it == table_.end()) { 4936a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes LOG(FATAL) << "IndexOf(\"" << s << "\") failed"; 4937a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes } 4938a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes return std::distance(table_.begin(), it); 4939545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 4940545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 4941a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes size_t Size() const { 4942545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes return table_.size(); 4943545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 4944545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 4945a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes void WriteTo(std::vector<uint8_t>& bytes) const { 494602e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier for (const std::string& str : table_) { 494702e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier const char* s = str.c_str(); 49486d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers size_t s_len = CountModifiedUtf8Chars(s); 49498a35405e00ad3a722750e37c8eae1c3e1cc0afb0Christopher Ferris std::unique_ptr<uint16_t[]> s_utf16(new uint16_t[s_len]); 49506d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers ConvertModifiedUtf8ToUtf16(s_utf16.get(), s); 49516d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers JDWP::AppendUtf16BE(bytes, s_utf16.get(), s_len); 4952545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 4953545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 4954545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 4955545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes private: 4956a8f93cbea2a094ac76e29d2ed17b8531b0a12cb6Elliott Hughes std::set<std::string> table_; 4957545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes DISALLOW_COPY_AND_ASSIGN(StringTable); 4958545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes}; 4959545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 4960e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic const char* GetMethodSourceFile(ArtMethod* method) 4961bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 4962bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier DCHECK(method != nullptr); 4963bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier const char* source_file = method->GetDeclaringClassSourceFile(); 4964280286ac8a0e3a30c68be511c8b7a0a4d62936d7Sebastien Hertz return (source_file != nullptr) ? source_file : ""; 4965280286ac8a0e3a30c68be511c8b7a0a4d62936d7Sebastien Hertz} 4966280286ac8a0e3a30c68be511c8b7a0a4d62936d7Sebastien Hertz 4967545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes/* 4968545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * The data we send to DDMS contains everything we have recorded. 4969545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * 4970545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * Message header (all values big-endian): 4971545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (1b) message header len (to allow future expansion); includes itself 4972545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (1b) entry header len 4973545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (1b) stack frame len 4974545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) number of entries 4975545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (4b) offset to string table from start of message 4976545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) number of class name strings 4977545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) number of method name strings 4978545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) number of source file name strings 4979545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * For each entry: 4980545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (4b) total allocation size 4981221229cb523f849f165fdafbf9785010963715daElliott Hughes * (2b) thread id 4982545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) allocated object's class name index 4983545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (1b) stack depth 4984545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * For each stack frame: 4985545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) method's class name 4986545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) method name 4987545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) method source file 4988545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (2b) line number, clipped to 32767; -2 if native; -1 if no source 4989545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (xb) class name strings 4990545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (xb) method name strings 4991545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * (xb) source file strings 4992545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * 4993545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * As with other DDM traffic, strings are sent as a 4-byte length 4994545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * followed by UTF-16 data. 4995545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * 4996545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * We send up 16-bit unsigned indexes into string tables. In theory there 4997306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom * can be (kMaxAllocRecordStackDepth * alloc_record_max_) unique strings in 4998545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * each table, but in practice there should be far fewer. 4999545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * 5000545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * The chief reason for using a string table here is to keep the size of 5001545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * the DDMS message to a minimum. This is partly to make the protocol 5002545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * efficient, but also because we have to form the whole thing up all at 5003545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * once in a memory buffer. 5004545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * 5005545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * We use separate string tables for class names, method names, and source 5006545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * files to keep the indexes small. There will generally be no overlap 5007545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes * between the contents of these tables. 5008545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes */ 5009545a064aca775ba801790fced3d713d8a87bfc61Elliott HughesjbyteArray Dbg::GetRecentAllocations() { 5010cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers if ((false)) { 5011545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes DumpRecentAllocations(); 5012545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 5013545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 501450b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers Thread* self = Thread::Current(); 501546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier std::vector<uint8_t> bytes; 501646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier { 5017306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom MutexLock mu(self, *Locks::alloc_tracker_lock_); 50188c2ff641294715864013737fdec57cdfd410270cMan Cao gc::AllocRecordObjectMap* records = Runtime::Current()->GetHeap()->GetAllocationRecords(); 50198c2ff641294715864013737fdec57cdfd410270cMan Cao // In case this method is called when allocation tracker is disabled, 50208c2ff641294715864013737fdec57cdfd410270cMan Cao // we should still send some data back. 50218c2ff641294715864013737fdec57cdfd410270cMan Cao gc::AllocRecordObjectMap dummy; 50228c2ff641294715864013737fdec57cdfd410270cMan Cao if (records == nullptr) { 50238c2ff641294715864013737fdec57cdfd410270cMan Cao CHECK(!Runtime::Current()->GetHeap()->IsAllocTrackingEnabled()); 50248c2ff641294715864013737fdec57cdfd410270cMan Cao records = &dummy; 50258c2ff641294715864013737fdec57cdfd410270cMan Cao } 502641656de4b6440bcd1bea5fb785f0710153b2bc68Man Cao // We don't need to wait on the condition variable records->new_record_condition_, because this 502741656de4b6440bcd1bea5fb785f0710153b2bc68Man Cao // function only reads the class objects, which are already marked so it doesn't change their 502841656de4b6440bcd1bea5fb785f0710153b2bc68Man Cao // reachability. 50298c2ff641294715864013737fdec57cdfd410270cMan Cao 503046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // 503146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // Part 1: generate string tables. 503246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // 503346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier StringTable class_names; 503446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier StringTable method_names; 503546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier StringTable filenames; 503646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier 50371ed11b9ad5512cf464cb1686640df53201fa5297Man Cao const uint16_t capped_count = CappedAllocRecordCount(records->GetRecentAllocationSize()); 5038306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom uint16_t count = capped_count; 50398c2ff641294715864013737fdec57cdfd410270cMan Cao for (auto it = records->RBegin(), end = records->REnd(); 50408c2ff641294715864013737fdec57cdfd410270cMan Cao count > 0 && it != end; count--, it++) { 5041458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier const gc::AllocRecord* record = &it->second; 50421ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers std::string temp; 504341656de4b6440bcd1bea5fb785f0710153b2bc68Man Cao class_names.Add(record->GetClassDescriptor(&temp)); 50448c2ff641294715864013737fdec57cdfd410270cMan Cao for (size_t i = 0, depth = record->GetDepth(); i < depth; i++) { 50458c2ff641294715864013737fdec57cdfd410270cMan Cao ArtMethod* m = record->StackElement(i).GetMethod(); 50468c2ff641294715864013737fdec57cdfd410270cMan Cao class_names.Add(m->GetDeclaringClassDescriptor()); 50478c2ff641294715864013737fdec57cdfd410270cMan Cao method_names.Add(m->GetName()); 50488c2ff641294715864013737fdec57cdfd410270cMan Cao filenames.Add(GetMethodSourceFile(m)); 504946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier } 505046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier } 505146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier 50528c2ff641294715864013737fdec57cdfd410270cMan Cao LOG(INFO) << "recent allocation records: " << capped_count; 50538c2ff641294715864013737fdec57cdfd410270cMan Cao LOG(INFO) << "allocation records all objects: " << records->Size(); 505446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier 505546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // 505646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // Part 2: Generate the output and store it in the buffer. 505746e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // 505846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier 505946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (1b) message header len (to allow future expansion); includes itself 506046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (1b) entry header len 506146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (1b) stack frame len 506246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier const int kMessageHeaderLen = 15; 506346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier const int kEntryHeaderLen = 9; 506446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier const int kStackFrameLen = 8; 506546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append1BE(bytes, kMessageHeaderLen); 506646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append1BE(bytes, kEntryHeaderLen); 506746e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append1BE(bytes, kStackFrameLen); 506846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier 506946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) number of entries 507046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (4b) offset to string table from start of message 507146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) number of class name strings 507246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) number of method name strings 507346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) number of source file name strings 5074306db81aba41eb244a4e8299cf58ac18ae9999c7Brian Carlstrom JDWP::Append2BE(bytes, capped_count); 507546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier size_t string_table_offset = bytes.size(); 50767934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom JDWP::Append4BE(bytes, 0); // We'll patch this later... 507746e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append2BE(bytes, class_names.Size()); 507846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append2BE(bytes, method_names.Size()); 507946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append2BE(bytes, filenames.Size()); 508046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier 50811ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers std::string temp; 50828c2ff641294715864013737fdec57cdfd410270cMan Cao count = capped_count; 50838c2ff641294715864013737fdec57cdfd410270cMan Cao // The last "count" number of allocation records in "records" are the most recent "count" number 50848c2ff641294715864013737fdec57cdfd410270cMan Cao // of allocations. Reverse iterate to get them. The most recent allocation is sent first. 50858c2ff641294715864013737fdec57cdfd410270cMan Cao for (auto it = records->RBegin(), end = records->REnd(); 50868c2ff641294715864013737fdec57cdfd410270cMan Cao count > 0 && it != end; count--, it++) { 508746e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // For each entry: 508846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (4b) total allocation size 508946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) thread id 509046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) allocated object's class name index 509146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (1b) stack depth 5092458b105a9cbab6156d72acf3b9372291dba9097aMathieu Chartier const gc::AllocRecord* record = &it->second; 509346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier size_t stack_depth = record->GetDepth(); 5094f832284dd847ff077577bb5712225430bbbb3b67Mathieu Chartier size_t allocated_object_class_name_index = 509541656de4b6440bcd1bea5fb785f0710153b2bc68Man Cao class_names.IndexOf(record->GetClassDescriptor(&temp)); 5096b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi JDWP::Append4BE(bytes, record->ByteCount()); 50978c2ff641294715864013737fdec57cdfd410270cMan Cao JDWP::Append2BE(bytes, static_cast<uint16_t>(record->GetTid())); 509846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append2BE(bytes, allocated_object_class_name_index); 509946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append1BE(bytes, stack_depth); 510046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier 510146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier for (size_t stack_frame = 0; stack_frame < stack_depth; ++stack_frame) { 510246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // For each stack frame: 510346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) method's class name 510446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) method name 510546e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) method source file 510646e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (2b) line number, clipped to 32767; -2 if native; -1 if no source 51078c2ff641294715864013737fdec57cdfd410270cMan Cao ArtMethod* m = record->StackElement(stack_frame).GetMethod(); 5108bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier size_t class_name_index = class_names.IndexOf(m->GetDeclaringClassDescriptor()); 5109bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier size_t method_name_index = method_names.IndexOf(m->GetName()); 5110bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier size_t file_name_index = filenames.IndexOf(GetMethodSourceFile(m)); 511146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append2BE(bytes, class_name_index); 511246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append2BE(bytes, method_name_index); 511346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Append2BE(bytes, file_name_index); 51148c2ff641294715864013737fdec57cdfd410270cMan Cao JDWP::Append2BE(bytes, record->StackElement(stack_frame).ComputeLineNumber()); 5115545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 5116545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 5117545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 511846e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (xb) class name strings 511946e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (xb) method name strings 512046e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier // (xb) source file strings 512146e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier JDWP::Set4BE(&bytes[string_table_offset], bytes.size()); 512246e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier class_names.WriteTo(bytes); 512346e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier method_names.WriteTo(bytes); 512446e811b07533a4c21f8c9abe22d22d6a3d8b18b0Mathieu Chartier filenames.WriteTo(bytes); 5125545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 512650b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers JNIEnv* env = self->GetJniEnv(); 5127545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes jbyteArray result = env->NewByteArray(bytes.size()); 5128c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers if (result != nullptr) { 5129545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes env->SetByteArrayRegion(result, 0, bytes.size(), reinterpret_cast<const jbyte*>(&bytes[0])); 5130545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 5131545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes return result; 5132545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes} 5133545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 5134e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu ChartierArtMethod* DeoptimizationRequest::Method() const { 513513b27842e88ccf1a42807c92daeb108e867dc4cdAndreas Gampe return jni::DecodeArtMethod(method_); 51360ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi} 51370ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi 5138e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid DeoptimizationRequest::SetMethod(ArtMethod* m) { 513913b27842e88ccf1a42807c92daeb108e867dc4cdAndreas Gampe method_ = jni::EncodeArtMethod(m); 51400ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi} 51410ec17d2ddb69d3f5c46ccad62e82c0ffd6219428Hiroshi Yamauchi 5142a6b1ead81603513fd40b77fd72f06d8cb1f35276Mathieu Chartiervoid Dbg::VisitRoots(RootVisitor* visitor) { 5143a6b1ead81603513fd40b77fd72f06d8cb1f35276Mathieu Chartier // Visit breakpoint roots, used to prevent unloading of methods with breakpoints. 5144a6b1ead81603513fd40b77fd72f06d8cb1f35276Mathieu Chartier ReaderMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_); 5145a6b1ead81603513fd40b77fd72f06d8cb1f35276Mathieu Chartier BufferedRootVisitor<128> root_visitor(visitor, RootInfo(kRootVMInternal)); 5146a6b1ead81603513fd40b77fd72f06d8cb1f35276Mathieu Chartier for (Breakpoint& breakpoint : gBreakpoints) { 5147542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe breakpoint.Method()->VisitRoots(root_visitor, kRuntimePointerSize); 5148a6b1ead81603513fd40b77fd72f06d8cb1f35276Mathieu Chartier } 5149a6b1ead81603513fd40b77fd72f06d8cb1f35276Mathieu Chartier} 5150a6b1ead81603513fd40b77fd72f06d8cb1f35276Mathieu Chartier 515104bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas Gampevoid Dbg::DbgThreadLifecycleCallback::ThreadStart(Thread* self) { 515204bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas Gampe Dbg::PostThreadStart(self); 515304bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas Gampe} 515404bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas Gampe 515504bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas Gampevoid Dbg::DbgThreadLifecycleCallback::ThreadDeath(Thread* self) { 515604bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas Gampe Dbg::PostThreadDeath(self); 515704bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas Gampe} 515804bbb5be5b9c0f0b3a72116353d23ea63c8bc5e9Andreas Gampe 51590f01b583c3952d0219696480654a0db8fac4b661Andreas Gampevoid Dbg::DbgClassLoadCallback::ClassLoad(Handle<mirror::Class> klass ATTRIBUTE_UNUSED) { 51600f01b583c3952d0219696480654a0db8fac4b661Andreas Gampe // Ignore ClassLoad; 51610f01b583c3952d0219696480654a0db8fac4b661Andreas Gampe} 51620f01b583c3952d0219696480654a0db8fac4b661Andreas Gampevoid Dbg::DbgClassLoadCallback::ClassPrepare(Handle<mirror::Class> temp_klass ATTRIBUTE_UNUSED, 51630f01b583c3952d0219696480654a0db8fac4b661Andreas Gampe Handle<mirror::Class> klass) { 51640f01b583c3952d0219696480654a0db8fac4b661Andreas Gampe Dbg::PostClassPrepare(klass.Get()); 51650f01b583c3952d0219696480654a0db8fac4b661Andreas Gampe} 51660f01b583c3952d0219696480654a0db8fac4b661Andreas Gampe 5167872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} // namespace art 5168