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 1707ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include <errno.h> 1807ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include <stdlib.h> 1907ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include <sys/time.h> 2007ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include <time.h> 2107ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include <unistd.h> 22872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 23872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "atomic.h" 2407ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h" 2541b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko#include "base/time_utils.h" 26872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "debugger.h" 27872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_priv.h" 2800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h" 29872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 30872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace art { 31872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 32872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace JDWP { 33872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 34376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesstatic void* StartJdwpThread(void* arg); 35872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 36872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 37872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * JdwpNetStateBase class implementation 38872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 395d10a87ea630b22180d3731018a70b77270c726eElliott HughesJdwpNetStateBase::JdwpNetStateBase(JdwpState* state) 404b95e8fad803ad307fa09c11c08894544e07a731Mathieu Chartier : state_(state), socket_lock_("JdwpNetStateBase lock", kJdwpSocketLock) { 41872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes clientSock = -1; 425d10a87ea630b22180d3731018a70b77270c726eElliott Hughes wake_pipe_[0] = -1; 435d10a87ea630b22180d3731018a70b77270c726eElliott Hughes wake_pipe_[1] = -1; 445d10a87ea630b22180d3731018a70b77270c726eElliott Hughes input_count_ = 0; 4568a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes awaiting_handshake_ = false; 46cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes} 47cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes 485d10a87ea630b22180d3731018a70b77270c726eElliott HughesJdwpNetStateBase::~JdwpNetStateBase() { 495d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (wake_pipe_[0] != -1) { 505d10a87ea630b22180d3731018a70b77270c726eElliott Hughes close(wake_pipe_[0]); 515d10a87ea630b22180d3731018a70b77270c726eElliott Hughes wake_pipe_[0] = -1; 525d10a87ea630b22180d3731018a70b77270c726eElliott Hughes } 535d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (wake_pipe_[1] != -1) { 545d10a87ea630b22180d3731018a70b77270c726eElliott Hughes close(wake_pipe_[1]); 555d10a87ea630b22180d3731018a70b77270c726eElliott Hughes wake_pipe_[1] = -1; 565d10a87ea630b22180d3731018a70b77270c726eElliott Hughes } 575d10a87ea630b22180d3731018a70b77270c726eElliott Hughes} 585d10a87ea630b22180d3731018a70b77270c726eElliott Hughes 595d10a87ea630b22180d3731018a70b77270c726eElliott Hughesbool JdwpNetStateBase::MakePipe() { 605d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (pipe(wake_pipe_) == -1) { 615d10a87ea630b22180d3731018a70b77270c726eElliott Hughes PLOG(ERROR) << "pipe failed"; 625d10a87ea630b22180d3731018a70b77270c726eElliott Hughes return false; 635d10a87ea630b22180d3731018a70b77270c726eElliott Hughes } 645d10a87ea630b22180d3731018a70b77270c726eElliott Hughes return true; 655d10a87ea630b22180d3731018a70b77270c726eElliott Hughes} 665d10a87ea630b22180d3731018a70b77270c726eElliott Hughes 675d10a87ea630b22180d3731018a70b77270c726eElliott Hughesvoid JdwpNetStateBase::WakePipe() { 685d10a87ea630b22180d3731018a70b77270c726eElliott Hughes // If we might be sitting in select, kick us loose. 695d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (wake_pipe_[1] != -1) { 705d10a87ea630b22180d3731018a70b77270c726eElliott Hughes VLOG(jdwp) << "+++ writing to wake pipe"; 715d10a87ea630b22180d3731018a70b77270c726eElliott Hughes TEMP_FAILURE_RETRY(write(wake_pipe_[1], "", 1)); 725d10a87ea630b22180d3731018a70b77270c726eElliott Hughes } 735d10a87ea630b22180d3731018a70b77270c726eElliott Hughes} 745d10a87ea630b22180d3731018a70b77270c726eElliott Hughes 75cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughesvoid JdwpNetStateBase::ConsumeBytes(size_t count) { 76cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes CHECK_GT(count, 0U); 775d10a87ea630b22180d3731018a70b77270c726eElliott Hughes CHECK_LE(count, input_count_); 78cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes 795d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (count == input_count_) { 805d10a87ea630b22180d3731018a70b77270c726eElliott Hughes input_count_ = 0; 81cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes return; 82cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes } 83cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes 845d10a87ea630b22180d3731018a70b77270c726eElliott Hughes memmove(input_buffer_, input_buffer_ + count, input_count_ - count); 855d10a87ea630b22180d3731018a70b77270c726eElliott Hughes input_count_ -= count; 86872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 87872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 8868a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughesbool JdwpNetStateBase::HaveFullPacket() { 8968a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes if (awaiting_handshake_) { 905d10a87ea630b22180d3731018a70b77270c726eElliott Hughes return (input_count_ >= kMagicHandshakeLen); 9168a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes } 925d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (input_count_ < 4) { 9368a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes return false; 9468a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes } 955d10a87ea630b22180d3731018a70b77270c726eElliott Hughes uint32_t length = Get4BE(input_buffer_); 965d10a87ea630b22180d3731018a70b77270c726eElliott Hughes return (input_count_ >= length); 9768a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes} 9868a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes 9968a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughesbool JdwpNetStateBase::IsAwaitingHandshake() { 10068a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes return awaiting_handshake_; 10168a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes} 10268a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes 10368a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughesvoid JdwpNetStateBase::SetAwaitingHandshake(bool new_state) { 10468a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes awaiting_handshake_ = new_state; 10568a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes} 10668a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes 10768a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughesbool JdwpNetStateBase::IsConnected() { 10868a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes return clientSock >= 0; 10968a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes} 11068a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes 11168a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes// Close a connection from a debugger (which may have already dropped us). 11268a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes// Resets the state so we're ready to receive a new connection. 11368a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes// Only called from the JDWP thread. 11468a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughesvoid JdwpNetStateBase::Close() { 11568a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes if (clientSock < 0) { 11668a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes return; 11768a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes } 11868a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes 11968a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes VLOG(jdwp) << "+++ closing JDWP connection on fd " << clientSock; 12068a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes 12168a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes close(clientSock); 12268a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes clientSock = -1; 12368a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes} 12468a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes 125872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 12643c8d729556844d1a74449a8a300c795d6a5406aSebastien Hertz * Write a packet of "length" bytes. Grabs a mutex to assure atomicity. 127872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 12843c8d729556844d1a74449a8a300c795d6a5406aSebastien Hertzssize_t JdwpNetStateBase::WritePacket(ExpandBuf* pReply, size_t length) { 12950b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu(Thread::Current(), socket_lock_); 1304e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz DCHECK(IsConnected()) << "Connection with debugger is closed"; 13143c8d729556844d1a74449a8a300c795d6a5406aSebastien Hertz DCHECK_LE(length, expandBufGetLength(pReply)); 13243c8d729556844d1a74449a8a300c795d6a5406aSebastien Hertz return TEMP_FAILURE_RETRY(write(clientSock, expandBufGetBuffer(pReply), length)); 133872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 134872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 135872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 136872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Write a buffered packet. Grabs a mutex to assure atomicity. 137872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 138f52935278fca8c7aa220543eef4544e3d1105d91Brian Carlstromssize_t JdwpNetStateBase::WriteBufferedPacket(const std::vector<iovec>& iov) { 13950b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu(Thread::Current(), socket_lock_); 140ad466adf38db74a9840659626858196091151a64Mathieu Chartier return WriteBufferedPacketLocked(iov); 141ad466adf38db74a9840659626858196091151a64Mathieu Chartier} 142ad466adf38db74a9840659626858196091151a64Mathieu Chartier 143ad466adf38db74a9840659626858196091151a64Mathieu Chartierssize_t JdwpNetStateBase::WriteBufferedPacketLocked(const std::vector<iovec>& iov) { 144ad466adf38db74a9840659626858196091151a64Mathieu Chartier socket_lock_.AssertHeld(Thread::Current()); 1454e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz DCHECK(IsConnected()) << "Connection with debugger is closed"; 146f52935278fca8c7aa220543eef4544e3d1105d91Brian Carlstrom return TEMP_FAILURE_RETRY(writev(clientSock, &iov[0], iov.size())); 147872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 148872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 149376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesbool JdwpState::IsConnected() { 1507d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz return netState != nullptr && netState->IsConnected(); 151872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 152872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 153f52935278fca8c7aa220543eef4544e3d1105d91Brian Carlstromvoid JdwpState::SendBufferedRequest(uint32_t type, const std::vector<iovec>& iov) { 15460ed7da4d193e0f90b05c4236af77d3b276c0ea4Sebastien Hertz if (!IsConnected()) { 15568a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes // Can happen with some DDMS events. 15668a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes VLOG(jdwp) << "Not sending JDWP packet: no debugger attached!"; 15768a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes return; 15868a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes } 15968a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes 16068a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes size_t expected = 0; 161f52935278fca8c7aa220543eef4544e3d1105d91Brian Carlstrom for (size_t i = 0; i < iov.size(); ++i) { 16268a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes expected += iov[i].iov_len; 16368a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes } 16468a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes 16568a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes errno = 0; 166f52935278fca8c7aa220543eef4544e3d1105d91Brian Carlstrom ssize_t actual = netState->WriteBufferedPacket(iov); 16768a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes if (static_cast<size_t>(actual) != expected) { 168d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers PLOG(ERROR) << StringPrintf("Failed to send JDWP packet %c%c%c%c to debugger (%zd of %zu)", 169d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers static_cast<char>(type >> 24), 170d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers static_cast<char>(type >> 16), 171d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers static_cast<char>(type >> 8), 172d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers static_cast<char>(type), 17368a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes actual, expected); 17468a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes } 17568a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes} 17668a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes 17768a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughesvoid JdwpState::SendRequest(ExpandBuf* pReq) { 17860ed7da4d193e0f90b05c4236af77d3b276c0ea4Sebastien Hertz if (!IsConnected()) { 17968a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes // Can happen with some DDMS events. 18068a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes VLOG(jdwp) << "Not sending JDWP packet: no debugger attached!"; 18168a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes return; 18268a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes } 18368a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes 18468a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes errno = 0; 18543c8d729556844d1a74449a8a300c795d6a5406aSebastien Hertz ssize_t actual = netState->WritePacket(pReq, expandBufGetLength(pReq)); 18668a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes if (static_cast<size_t>(actual) != expandBufGetLength(pReq)) { 187d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers PLOG(ERROR) << StringPrintf("Failed to send JDWP packet to debugger (%zd of %zu)", 18868a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes actual, expandBufGetLength(pReq)); 18968a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes } 190872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 191872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 192376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes/* 193376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes * Get the next "request" serial number. We use this when sending 194376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes * packets to the debugger. 195376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes */ 196376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesuint32_t JdwpState::NextRequestSerial() { 197f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes return request_serial_++; 198872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 199872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 200376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes/* 201376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes * Get the next "event" serial number. We use this in the response to 202376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes * message type EventRequest.Set. 203376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes */ 204376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesuint32_t JdwpState::NextEventSerial() { 205f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes return event_serial_++; 206872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 207872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 208376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott HughesJdwpState::JdwpState(const JdwpOptions* options) 209376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes : options_(options), 2100dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao thread_start_lock_("JDWP thread start lock", kJdwpStartLock), 211c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers thread_start_cond_("JDWP thread start condition variable", thread_start_lock_), 21200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers pthread_(0), 2137d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz thread_(nullptr), 214872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes debug_thread_started_(false), 215a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes debug_thread_id_(0), 216872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes run(false), 2177d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz netState(nullptr), 2180dfbb7ead0b6da92911b4bc78114ff0f0f9b4129jeffhao attach_lock_("JDWP attach lock", kJdwpAttachLock), 219c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers attach_cond_("JDWP attach condition variable", attach_lock_), 220a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes last_activity_time_ms_(0), 221f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes request_serial_(0x10000000), 222f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes event_serial_(0x20000000), 223a77f0f68a59870ff027dad654fe31eb3fdaf3d5djeffhao event_list_lock_("JDWP event list lock", kJdwpEventListLock), 2247d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz event_list_(nullptr), 225f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes event_list_size_(0), 2262bf93f48bbb417b358c9e3c77911ea6ec7307c15Sebastien Hertz jdwp_token_lock_("JDWP token lock"), 2272bf93f48bbb417b358c9e3c77911ea6ec7307c15Sebastien Hertz jdwp_token_cond_("JDWP token condition variable", jdwp_token_lock_), 2282bf93f48bbb417b358c9e3c77911ea6ec7307c15Sebastien Hertz jdwp_token_owner_thread_id_(0), 22964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes ddm_is_active_(false), 23064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes should_exit_(false), 2314e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz exit_status_(0), 2324e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz shutdown_lock_("JDWP shutdown lock", kJdwpShutdownLock), 2334e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz shutdown_cond_("JDWP shutdown condition variable", shutdown_lock_), 2344e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz processing_request_(false) { 235872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 236872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 237872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 238872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Initialize JDWP. 239872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 240872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Does not return until JDWP thread is running, but may return before 241872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * the thread is accepting network connections. 242872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 243376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott HughesJdwpState* JdwpState::Create(const JdwpOptions* options) { 24481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers Thread* self = Thread::Current(); 24581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers Locks::mutator_lock_->AssertNotHeld(self); 246700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<JdwpState> state(new JdwpState(options)); 247376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes switch (options->transport) { 248bb5c355df9d93d103f1a008fba485d03c56465b5Sebastien Hertz case kJdwpTransportSocket: 249bb5c355df9d93d103f1a008fba485d03c56465b5Sebastien Hertz InitSocketTransport(state.get(), options); 250bb5c355df9d93d103f1a008fba485d03c56465b5Sebastien Hertz break; 251872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#ifdef HAVE_ANDROID_OS 252bb5c355df9d93d103f1a008fba485d03c56465b5Sebastien Hertz case kJdwpTransportAndroidAdb: 253bb5c355df9d93d103f1a008fba485d03c56465b5Sebastien Hertz InitAdbTransport(state.get(), options); 254bb5c355df9d93d103f1a008fba485d03c56465b5Sebastien Hertz break; 255872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#endif 256bb5c355df9d93d103f1a008fba485d03c56465b5Sebastien Hertz default: 257bb5c355df9d93d103f1a008fba485d03c56465b5Sebastien Hertz LOG(FATAL) << "Unknown transport: " << options->transport; 258872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 259872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 260bb5c355df9d93d103f1a008fba485d03c56465b5Sebastien Hertz { 261add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao /* 262add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao * Grab a mutex before starting the thread. This ensures they 263add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao * won't signal the cond var before we're waiting. 264add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao */ 26550b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock thread_start_locker(self, state->thread_start_lock_); 266bb5c355df9d93d103f1a008fba485d03c56465b5Sebastien Hertz 267add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao /* 268add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao * We have bound to a port, or are trying to connect outbound to a 269add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao * debugger. Create the JDWP thread and let it continue the mission. 270add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao */ 271bb5c355df9d93d103f1a008fba485d03c56465b5Sebastien Hertz CHECK_PTHREAD_CALL(pthread_create, (&state->pthread_, nullptr, StartJdwpThread, state.get()), 272bb5c355df9d93d103f1a008fba485d03c56465b5Sebastien Hertz "JDWP thread"); 273add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao 274add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao /* 275add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao * Wait until the thread finishes basic initialization. 276add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao */ 277bb5c355df9d93d103f1a008fba485d03c56465b5Sebastien Hertz while (!state->debug_thread_started_) { 278c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers state->thread_start_cond_.Wait(self); 279add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao } 280bb5c355df9d93d103f1a008fba485d03c56465b5Sebastien Hertz } 281872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 282bb5c355df9d93d103f1a008fba485d03c56465b5Sebastien Hertz if (options->suspend) { 283add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao /* 284add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao * For suspend=y, wait for the debugger to connect to us or for us to 285add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao * connect to the debugger. 286add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao * 287add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao * The JDWP thread will signal us when it connects successfully or 288add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao * times out (for timeout=xxx), so we have to check to see what happened 289add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao * when we wake up. 290add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao */ 291add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao { 292add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao ScopedThreadStateChange tsc(self, kWaitingForDebuggerToAttach); 293add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao MutexLock attach_locker(self, state->attach_lock_); 294c6345efb56f9096c4b1a1a90e1d8d847fc01d910Sebastien Hertz while (state->debug_thread_id_ == 0) { 295c6345efb56f9096c4b1a1a90e1d8d847fc01d910Sebastien Hertz state->attach_cond_.Wait(self); 296c6345efb56f9096c4b1a1a90e1d8d847fc01d910Sebastien Hertz } 297add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao } 298add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao if (!state->IsActive()) { 299add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao LOG(ERROR) << "JDWP connection failed"; 3007d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz return nullptr; 301872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 302add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao 303add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao LOG(INFO) << "JDWP connected"; 304add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao 305add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao /* 306add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao * Ordinarily we would pause briefly to allow the debugger to set 307add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao * breakpoints and so on, but for "suspend=y" the VM init code will 308add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao * pause the VM when it sends the VM_START message. 309add037df2399821eb048a5d9146a9d2174bcd1bdJeff Hao */ 310872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 311872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 312761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes return state.release(); 313872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 314872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 315872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 316872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Reset all session-related state. There should not be an active connection 317872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * to the client at this point. The rest of the VM still thinks there is 318872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * a debugger attached. 319872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 320872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * This includes freeing up the debugger event list. 321872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 322376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesvoid JdwpState::ResetState() { 323872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* could reset the serial numbers, but no need to */ 324872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 325761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes UnregisterAll(); 326f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes { 32750b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu(Thread::Current(), event_list_lock_); 3287d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz CHECK(event_list_ == nullptr); 329f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes } 330872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 331872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* 332872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Should not have one of these in progress. If the debugger went away 333872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * mid-request, though, we could see this. 334872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 3352bf93f48bbb417b358c9e3c77911ea6ec7307c15Sebastien Hertz if (jdwp_token_owner_thread_id_ != 0) { 3363d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes LOG(WARNING) << "Resetting state while event in progress"; 337872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes DCHECK(false); 338872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 339872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 340872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 341872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 342872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Tell the JDWP thread to shut down. Frees "state". 343872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 344376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott HughesJdwpState::~JdwpState() { 3457d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz if (netState != nullptr) { 346872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* 3474e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz * Close down the network to inspire the thread to halt. If a request is being processed, 3484e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz * we need to wait for it to finish first. 349872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 3504e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz { 3514e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz Thread* self = Thread::Current(); 3524e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz MutexLock mu(self, shutdown_lock_); 3534e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz while (processing_request_) { 3544e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz VLOG(jdwp) << "JDWP command in progress: wait for it to finish ..."; 3554e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz shutdown_cond_.Wait(self); 3564e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz } 3574e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz 3584e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz VLOG(jdwp) << "JDWP shutting down net..."; 3594e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz netState->Shutdown(); 3604e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz } 361872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 362376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes if (debug_thread_started_) { 363376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes run = false; 364376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes void* threadReturn; 365475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes if (pthread_join(pthread_, &threadReturn) != 0) { 366872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes LOG(WARNING) << "JDWP thread join failed"; 367872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 368872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 369872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 3700cc1bbd9247151289db88ccea89c842953323a6aElliott Hughes VLOG(jdwp) << "JDWP freeing netstate..."; 3715d10a87ea630b22180d3731018a70b77270c726eElliott Hughes delete netState; 3727d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz netState = nullptr; 373872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 3747d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz CHECK(netState == nullptr); 375872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 376376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes ResetState(); 377872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 378872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 379872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 380872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Are we talking to a debugger? 381872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 382376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesbool JdwpState::IsActive() { 383376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes return IsConnected(); 384872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 385872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 386cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes// Returns "false" if we encounter a connection-fatal error. 387cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughesbool JdwpState::HandlePacket() { 3884e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz Thread* const self = Thread::Current(); 3894e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz { 3904e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz MutexLock mu(self, shutdown_lock_); 3914e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz processing_request_ = true; 3924e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz } 3934e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz JdwpNetStateBase* netStateBase = netState; 3944e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz CHECK(netStateBase != nullptr) << "Connection has been closed"; 3955d10a87ea630b22180d3731018a70b77270c726eElliott Hughes JDWP::Request request(netStateBase->input_buffer_, netStateBase->input_count_); 396cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes 397cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes ExpandBuf* pReply = expandBufAlloc(); 3986ba35b50347aa7418c66c7b046cd164987e95df3Sebastien Hertz bool skip_reply = false; 3996ba35b50347aa7418c66c7b046cd164987e95df3Sebastien Hertz size_t replyLength = ProcessRequest(&request, pReply, &skip_reply); 4006ba35b50347aa7418c66c7b046cd164987e95df3Sebastien Hertz ssize_t cc = 0; 4016ba35b50347aa7418c66c7b046cd164987e95df3Sebastien Hertz if (!skip_reply) { 4026ba35b50347aa7418c66c7b046cd164987e95df3Sebastien Hertz cc = netStateBase->WritePacket(pReply, replyLength); 4036ba35b50347aa7418c66c7b046cd164987e95df3Sebastien Hertz } else { 4046ba35b50347aa7418c66c7b046cd164987e95df3Sebastien Hertz DCHECK_EQ(replyLength, 0U); 4056ba35b50347aa7418c66c7b046cd164987e95df3Sebastien Hertz } 4066ba35b50347aa7418c66c7b046cd164987e95df3Sebastien Hertz expandBufFree(pReply); 407400a3a9d332ee17e69b876cbbfb47d9e576fc4f2Sebastien Hertz 408400a3a9d332ee17e69b876cbbfb47d9e576fc4f2Sebastien Hertz /* 4092bf93f48bbb417b358c9e3c77911ea6ec7307c15Sebastien Hertz * We processed this request and sent its reply so we can release the JDWP token. 410400a3a9d332ee17e69b876cbbfb47d9e576fc4f2Sebastien Hertz */ 4112bf93f48bbb417b358c9e3c77911ea6ec7307c15Sebastien Hertz ReleaseJdwpTokenForCommand(); 41299660e1c3d6117cfb8bac25b1a0413833ab15b2aSebastien Hertz 41343c8d729556844d1a74449a8a300c795d6a5406aSebastien Hertz if (cc != static_cast<ssize_t>(replyLength)) { 414cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes PLOG(ERROR) << "Failed sending reply to debugger"; 415cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes return false; 416cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes } 417cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes netStateBase->ConsumeBytes(request.GetLength()); 4184e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz { 4194e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz MutexLock mu(self, shutdown_lock_); 4204e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz processing_request_ = false; 4214e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz shutdown_cond_.Broadcast(self); 4224e5b20863898006ec6c9d120cda167d38dda6e60Sebastien Hertz } 423cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes return true; 424cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes} 425cb69306eefc1e6e42b3eaec8b479a268222b01b6Elliott Hughes 426872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 427872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Entry point for JDWP thread. The thread was created through the VM 428872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * mechanisms, so there is a java/lang/Thread associated with us. 429872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 430376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesstatic void* StartJdwpThread(void* arg) { 431872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes JdwpState* state = reinterpret_cast<JdwpState*>(arg); 4327d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz CHECK(state != nullptr); 433872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 434376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes state->Run(); 4357d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz return nullptr; 436376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes} 437376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes 438376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesvoid JdwpState::Run() { 439872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes Runtime* runtime = Runtime::Current(); 440664bebf92eb2151b9b570ccd42ac4b6056c3ea9cMathieu Chartier CHECK(runtime->AttachCurrentThread("JDWP", true, runtime->GetSystemThreadGroup(), 441184c9dc3bfc500134fdb2fbea0a7fab290c0abb0Mathieu Chartier !runtime->IsAotCompiler())); 442872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 4434dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << "JDWP: thread running"; 444872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 445872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* 446376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes * Finish initializing, then notify the creating thread that 447872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * we're running. 448872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 449475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes thread_ = Thread::Current(); 450376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes run = true; 451872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 45281d425b0b232962441616f8b14f73620bffef5e5Ian Rogers { 45381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers MutexLock locker(thread_, thread_start_lock_); 45481d425b0b232962441616f8b14f73620bffef5e5Ian Rogers debug_thread_started_ = true; 455c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers thread_start_cond_.Broadcast(thread_); 45681d425b0b232962441616f8b14f73620bffef5e5Ian Rogers } 457872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 45800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers /* set the thread state to kWaitingInMainDebuggerLoop so GCs don't wait for us */ 45950b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers CHECK_EQ(thread_->GetState(), kNative); 46062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Locks::mutator_lock_->AssertNotHeld(thread_); 46150b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers thread_->SetState(kWaitingInMainDebuggerLoop); 462872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 463872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* 464872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Loop forever if we're in server mode, processing connections. In 465872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * non-server mode, we bail out of the thread when the debugger drops 466872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * us. 467872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 468872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * We broadcast a notification when a debugger attaches, after we 469872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * successfully process the handshake. 470872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 471376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes while (run) { 472376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes if (options_->server) { 473872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* 474872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Block forever, waiting for a connection. To support the 475872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * "timeout=xxx" option we'll need to tweak this. 476872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 4775d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (!netState->Accept()) { 478872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes break; 479872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 480872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } else { 481872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* 482872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * If we're not acting as a server, we need to connect out to the 483872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * debugger. To support the "timeout=xxx" option we need to 484872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * have a timeout if the handshake reply isn't received in a 485872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * reasonable amount of time. 486872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 4875d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (!netState->Establish(options_)) { 488872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* wake anybody who was waiting for us to succeed */ 48950b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers MutexLock mu(thread_, attach_lock_); 490c6345efb56f9096c4b1a1a90e1d8d847fc01d910Sebastien Hertz debug_thread_id_ = static_cast<ObjectId>(-1); 491c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers attach_cond_.Broadcast(thread_); 492872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes break; 493872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 494872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 495872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 496872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* prep debug code to handle the new connection */ 497872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes Dbg::Connected(); 498872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 499872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* process requests until the debugger drops */ 500376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes bool first = true; 5018696433d1b3d8ba15288483b777edd888de69135Elliott Hughes while (!Dbg::IsDisposed()) { 502bb5c355df9d93d103f1a008fba485d03c56465b5Sebastien Hertz // sanity check -- shouldn't happen? 503bb5c355df9d93d103f1a008fba485d03c56465b5Sebastien Hertz CHECK_EQ(thread_->GetState(), kWaitingInMainDebuggerLoop); 504872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 5055d10a87ea630b22180d3731018a70b77270c726eElliott Hughes if (!netState->ProcessIncoming()) { 506872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* blocking read */ 507872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes break; 508872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 509872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 51064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (should_exit_) { 51164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes exit(exit_status_); 51264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes } 51364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 51468a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes if (first && !netState->IsAwaitingHandshake()) { 515872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* handshake worked, tell the interpreter that we're active */ 516872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes first = false; 517872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 518872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* set thread ID; requires object registry to be active */ 51900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers { 52000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(thread_); 52100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers debug_thread_id_ = Dbg::GetThreadSelfId(); 52200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 523872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 524872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* wake anybody who's waiting for us */ 52581d425b0b232962441616f8b14f73620bffef5e5Ian Rogers MutexLock mu(thread_, attach_lock_); 526c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers attach_cond_.Broadcast(thread_); 527872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 528872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 529872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 53068a5e3c9115f9ba396563ce3b72df9cb036bc665Elliott Hughes netState->Close(); 531872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 532a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes if (ddm_is_active_) { 533a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes ddm_is_active_ = false; 534872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 535872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* broadcast the disconnect; must be in RUNNING state */ 53600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers thread_->TransitionFromSuspendedToRunnable(); 537872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes Dbg::DdmDisconnected(); 53800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers thread_->TransitionFromRunnableToSuspended(kWaitingInMainDebuggerLoop); 539872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 540872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 54100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers { 54200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(thread_); 5430f827169742aad6209d830db773a101849c32a83Elliott Hughes 5440f827169742aad6209d830db773a101849c32a83Elliott Hughes // Release session state, e.g. remove breakpoint instructions. 54500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ResetState(); 54600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 54762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // Tell the rest of the runtime that the debugger is no longer around. 54862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Dbg::Disconnected(); 549872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 550872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* if we had threads suspended, resume them now */ 551872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes Dbg::UndoDebuggerSuspensions(); 552872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 553872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* if we connected out, this was a one-shot deal */ 554376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes if (!options_->server) { 555376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes run = false; 556872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 557872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 558872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 55900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers /* back to native, for thread shutdown */ 56081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers CHECK_EQ(thread_->GetState(), kWaitingInMainDebuggerLoop); 56181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers thread_->SetState(kNative); 562872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 5634dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << "JDWP: thread detaching and exiting..."; 5646ba581a6711c4fed24828c9a294b1b49ac6bbb30Elliott Hughes runtime->DetachCurrentThread(); 565872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 566872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 567a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughesvoid JdwpState::NotifyDdmsActive() { 568a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes if (!ddm_is_active_) { 569a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes ddm_is_active_ = true; 570a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes Dbg::DdmConnected(); 571a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes } 572a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes} 573a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes 574475fc23a4a7f35d1be87ea0b06c80df317a720acElliott HughesThread* JdwpState::GetDebugThread() { 575475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes return thread_; 576872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 577872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 578872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 579872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Support routines for waitForDebugger(). 580872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 581872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * We can't have a trivial "waitForDebugger" function that returns the 582872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * instant the debugger connects, because we run the risk of executing code 583872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * before the debugger has had a chance to configure breakpoints or issue 584872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * suspend calls. It would be nice to just sit in the suspended state, but 585872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * most debuggers don't expect any threads to be suspended when they attach. 586872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 587872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * There's no JDWP event we can post to tell the debugger, "we've stopped, 588872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * and we like it that way". We could send a fake breakpoint, which should 589872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * cause the debugger to immediately send a resume, but the debugger might 590872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * send the resume immediately or might throw an exception of its own upon 591872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * receiving a breakpoint event that it didn't ask for. 592872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 593872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * What we really want is a "wait until the debugger is done configuring 594872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * stuff" event. We can approximate this with a "wait until the debugger 595872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * has been idle for a brief period". 596872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 597872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 598872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/* 599872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Return the time, in milliseconds, since the last debugger activity. 600872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * 601872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Returns -1 if no debugger is attached, or 0 if we're in the middle of 602872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * processing a debugger request. 603872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */ 604376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesint64_t JdwpState::LastDebuggerActivity() { 605c0f0933249cf516b37717faa766e1e9808f7c1f8Elliott Hughes if (!Dbg::IsDebuggerActive()) { 6064d466a8e4587422c989705dce3b2a19e7f0137f5Brian Carlstrom LOG(WARNING) << "no active debugger"; 607872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return -1; 608872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 609872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 61037f3c968ecd04e77802fe17bb82dabc07de21ca1Ian Rogers int64_t last = last_activity_time_ms_.LoadSequentiallyConsistent(); 611872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 612872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* initializing or in the middle of something? */ 613872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes if (last == 0) { 6144dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << "+++ last=busy"; 615872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return 0; 616872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes } 617872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 618872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes /* now get the current time */ 6197162ad937f5f6bec32bf78d4675ff65cd6d1a233Elliott Hughes int64_t now = MilliTime(); 620c3b3e75e2ec66b16214fcd56dd08c0d9f6b1a591Elliott Hughes CHECK_GE(now, last); 621872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 6224dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes VLOG(jdwp) << "+++ debugger interval=" << (now - last); 623872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes return now - last; 624872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} 625872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 62664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid JdwpState::ExitAfterReplying(int exit_status) { 62764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes LOG(WARNING) << "Debugger told VM to exit with status " << exit_status; 62864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes should_exit_ = true; 62964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes exit_status_ = exit_status; 63064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 63164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 63203181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughesstd::ostream& operator<<(std::ostream& os, const JdwpLocation& rhs) { 633d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes os << "JdwpLocation[" 634a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes << Dbg::GetClassName(rhs.class_id) << "." << Dbg::GetMethodName(rhs.method_id) 635d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers << "@" << StringPrintf("%#" PRIx64, rhs.dex_pc) << " " << rhs.type_tag << "]"; 63603181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes return os; 63703181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes} 63803181a828cd493545b278e0aa4f150fdaf1e3325Elliott Hughes 6392aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughesbool operator==(const JdwpLocation& lhs, const JdwpLocation& rhs) { 640748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes return lhs.dex_pc == rhs.dex_pc && lhs.method_id == rhs.method_id && 641748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes lhs.class_id == rhs.class_id && lhs.type_tag == rhs.type_tag; 6422aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes} 6432aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes 6442aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughesbool operator!=(const JdwpLocation& lhs, const JdwpLocation& rhs) { 6452aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes return !(lhs == rhs); 6462aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes} 6472aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes 648aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkinbool operator==(const JdwpOptions& lhs, const JdwpOptions& rhs) { 649aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin if (&lhs == &rhs) { 650aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return true; 651aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin } 652aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 653aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin return lhs.transport == rhs.transport && 654aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin lhs.server == rhs.server && 655aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin lhs.suspend == rhs.suspend && 656aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin lhs.host == rhs.host && 657aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin lhs.port == rhs.port; 658aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin} 659aaebaa0121be3b9d9f13630585304482cbcaeb4bIgor Murashkin 660872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} // namespace JDWP 661872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes 662872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes} // namespace art 663