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