1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <errno.h> 18#include <stdlib.h> 19#include <sys/time.h> 20#include <time.h> 21#include <unistd.h> 22 23#include "atomic.h" 24#include "base/logging.h" 25#include "base/time_utils.h" 26#include "debugger.h" 27#include "jdwp/jdwp_priv.h" 28#include "scoped_thread_state_change.h" 29 30namespace art { 31 32namespace JDWP { 33 34static void* StartJdwpThread(void* arg); 35 36/* 37 * JdwpNetStateBase class implementation 38 */ 39JdwpNetStateBase::JdwpNetStateBase(JdwpState* state) 40 : state_(state), socket_lock_("JdwpNetStateBase lock", kJdwpSocketLock) { 41 clientSock = -1; 42 wake_pipe_[0] = -1; 43 wake_pipe_[1] = -1; 44 input_count_ = 0; 45 awaiting_handshake_ = false; 46} 47 48JdwpNetStateBase::~JdwpNetStateBase() { 49 if (wake_pipe_[0] != -1) { 50 close(wake_pipe_[0]); 51 wake_pipe_[0] = -1; 52 } 53 if (wake_pipe_[1] != -1) { 54 close(wake_pipe_[1]); 55 wake_pipe_[1] = -1; 56 } 57} 58 59bool JdwpNetStateBase::MakePipe() { 60 if (pipe(wake_pipe_) == -1) { 61 PLOG(ERROR) << "pipe failed"; 62 return false; 63 } 64 return true; 65} 66 67void JdwpNetStateBase::WakePipe() { 68 // If we might be sitting in select, kick us loose. 69 if (wake_pipe_[1] != -1) { 70 VLOG(jdwp) << "+++ writing to wake pipe"; 71 TEMP_FAILURE_RETRY(write(wake_pipe_[1], "", 1)); 72 } 73} 74 75void JdwpNetStateBase::ConsumeBytes(size_t count) { 76 CHECK_GT(count, 0U); 77 CHECK_LE(count, input_count_); 78 79 if (count == input_count_) { 80 input_count_ = 0; 81 return; 82 } 83 84 memmove(input_buffer_, input_buffer_ + count, input_count_ - count); 85 input_count_ -= count; 86} 87 88bool JdwpNetStateBase::HaveFullPacket() { 89 if (awaiting_handshake_) { 90 return (input_count_ >= kMagicHandshakeLen); 91 } 92 if (input_count_ < 4) { 93 return false; 94 } 95 uint32_t length = Get4BE(input_buffer_); 96 return (input_count_ >= length); 97} 98 99bool JdwpNetStateBase::IsAwaitingHandshake() { 100 return awaiting_handshake_; 101} 102 103void JdwpNetStateBase::SetAwaitingHandshake(bool new_state) { 104 awaiting_handshake_ = new_state; 105} 106 107bool JdwpNetStateBase::IsConnected() { 108 return clientSock >= 0; 109} 110 111// Close a connection from a debugger (which may have already dropped us). 112// Resets the state so we're ready to receive a new connection. 113// Only called from the JDWP thread. 114void JdwpNetStateBase::Close() { 115 if (clientSock < 0) { 116 return; 117 } 118 119 VLOG(jdwp) << "+++ closing JDWP connection on fd " << clientSock; 120 121 close(clientSock); 122 clientSock = -1; 123} 124 125/* 126 * Write a packet of "length" bytes. Grabs a mutex to assure atomicity. 127 */ 128ssize_t JdwpNetStateBase::WritePacket(ExpandBuf* pReply, size_t length) { 129 DCHECK_LE(length, expandBufGetLength(pReply)); 130 if (!IsConnected()) { 131 LOG(WARNING) << "Connection with debugger is closed"; 132 return -1; 133 } 134 MutexLock mu(Thread::Current(), socket_lock_); 135 return TEMP_FAILURE_RETRY(write(clientSock, expandBufGetBuffer(pReply), length)); 136} 137 138/* 139 * Write a buffered packet. Grabs a mutex to assure atomicity. 140 */ 141ssize_t JdwpNetStateBase::WriteBufferedPacket(const std::vector<iovec>& iov) { 142 MutexLock mu(Thread::Current(), socket_lock_); 143 return WriteBufferedPacketLocked(iov); 144} 145 146ssize_t JdwpNetStateBase::WriteBufferedPacketLocked(const std::vector<iovec>& iov) { 147 socket_lock_.AssertHeld(Thread::Current()); 148 DCHECK(IsConnected()) << "Connection with debugger is closed"; 149 return TEMP_FAILURE_RETRY(writev(clientSock, &iov[0], iov.size())); 150} 151 152bool JdwpState::IsConnected() { 153 return netState != nullptr && netState->IsConnected(); 154} 155 156void JdwpState::SendBufferedRequest(uint32_t type, const std::vector<iovec>& iov) { 157 if (!IsConnected()) { 158 // Can happen with some DDMS events. 159 VLOG(jdwp) << "Not sending JDWP packet: no debugger attached!"; 160 return; 161 } 162 163 size_t expected = 0; 164 for (size_t i = 0; i < iov.size(); ++i) { 165 expected += iov[i].iov_len; 166 } 167 168 errno = 0; 169 ssize_t actual = netState->WriteBufferedPacket(iov); 170 if (static_cast<size_t>(actual) != expected) { 171 PLOG(ERROR) << StringPrintf("Failed to send JDWP packet %c%c%c%c to debugger (%zd of %zu)", 172 static_cast<char>(type >> 24), 173 static_cast<char>(type >> 16), 174 static_cast<char>(type >> 8), 175 static_cast<char>(type), 176 actual, expected); 177 } 178} 179 180void JdwpState::SendRequest(ExpandBuf* pReq) { 181 if (!IsConnected()) { 182 // Can happen with some DDMS events. 183 VLOG(jdwp) << "Not sending JDWP packet: no debugger attached!"; 184 return; 185 } 186 187 errno = 0; 188 ssize_t actual = netState->WritePacket(pReq, expandBufGetLength(pReq)); 189 if (static_cast<size_t>(actual) != expandBufGetLength(pReq)) { 190 PLOG(ERROR) << StringPrintf("Failed to send JDWP packet to debugger (%zd of %zu)", 191 actual, expandBufGetLength(pReq)); 192 } 193} 194 195/* 196 * Get the next "request" serial number. We use this when sending 197 * packets to the debugger. 198 */ 199uint32_t JdwpState::NextRequestSerial() { 200 return request_serial_++; 201} 202 203/* 204 * Get the next "event" serial number. We use this in the response to 205 * message type EventRequest.Set. 206 */ 207uint32_t JdwpState::NextEventSerial() { 208 return event_serial_++; 209} 210 211JdwpState::JdwpState(const JdwpOptions* options) 212 : options_(options), 213 thread_start_lock_("JDWP thread start lock", kJdwpStartLock), 214 thread_start_cond_("JDWP thread start condition variable", thread_start_lock_), 215 pthread_(0), 216 thread_(nullptr), 217 debug_thread_started_(false), 218 debug_thread_id_(0), 219 run(false), 220 netState(nullptr), 221 attach_lock_("JDWP attach lock", kJdwpAttachLock), 222 attach_cond_("JDWP attach condition variable", attach_lock_), 223 last_activity_time_ms_(0), 224 request_serial_(0x10000000), 225 event_serial_(0x20000000), 226 event_list_lock_("JDWP event list lock", kJdwpEventListLock), 227 event_list_(nullptr), 228 event_list_size_(0), 229 jdwp_token_lock_("JDWP token lock"), 230 jdwp_token_cond_("JDWP token condition variable", jdwp_token_lock_), 231 jdwp_token_owner_thread_id_(0), 232 ddm_is_active_(false), 233 should_exit_(false), 234 exit_status_(0), 235 shutdown_lock_("JDWP shutdown lock", kJdwpShutdownLock), 236 shutdown_cond_("JDWP shutdown condition variable", shutdown_lock_), 237 processing_request_(false) { 238} 239 240/* 241 * Initialize JDWP. 242 * 243 * Does not return until JDWP thread is running, but may return before 244 * the thread is accepting network connections. 245 */ 246JdwpState* JdwpState::Create(const JdwpOptions* options) { 247 Thread* self = Thread::Current(); 248 Locks::mutator_lock_->AssertNotHeld(self); 249 std::unique_ptr<JdwpState> state(new JdwpState(options)); 250 switch (options->transport) { 251 case kJdwpTransportSocket: 252 InitSocketTransport(state.get(), options); 253 break; 254#ifdef __ANDROID__ 255 case kJdwpTransportAndroidAdb: 256 InitAdbTransport(state.get(), options); 257 break; 258#endif 259 default: 260 LOG(FATAL) << "Unknown transport: " << options->transport; 261 } 262 { 263 /* 264 * Grab a mutex before starting the thread. This ensures they 265 * won't signal the cond var before we're waiting. 266 */ 267 state->thread_start_lock_.AssertNotHeld(self); 268 MutexLock thread_start_locker(self, state->thread_start_lock_); 269 270 /* 271 * We have bound to a port, or are trying to connect outbound to a 272 * debugger. Create the JDWP thread and let it continue the mission. 273 */ 274 CHECK_PTHREAD_CALL(pthread_create, (&state->pthread_, nullptr, StartJdwpThread, state.get()), 275 "JDWP thread"); 276 277 /* 278 * Wait until the thread finishes basic initialization. 279 */ 280 while (!state->debug_thread_started_) { 281 state->thread_start_cond_.Wait(self); 282 } 283 } 284 285 if (options->suspend) { 286 /* 287 * For suspend=y, wait for the debugger to connect to us or for us to 288 * connect to the debugger. 289 * 290 * The JDWP thread will signal us when it connects successfully or 291 * times out (for timeout=xxx), so we have to check to see what happened 292 * when we wake up. 293 */ 294 { 295 ScopedThreadStateChange tsc(self, kWaitingForDebuggerToAttach); 296 MutexLock attach_locker(self, state->attach_lock_); 297 while (state->debug_thread_id_ == 0) { 298 state->attach_cond_.Wait(self); 299 } 300 } 301 if (!state->IsActive()) { 302 LOG(ERROR) << "JDWP connection failed"; 303 return nullptr; 304 } 305 306 LOG(INFO) << "JDWP connected"; 307 308 /* 309 * Ordinarily we would pause briefly to allow the debugger to set 310 * breakpoints and so on, but for "suspend=y" the VM init code will 311 * pause the VM when it sends the VM_START message. 312 */ 313 } 314 315 return state.release(); 316} 317 318/* 319 * Reset all session-related state. There should not be an active connection 320 * to the client at this point. The rest of the VM still thinks there is 321 * a debugger attached. 322 * 323 * This includes freeing up the debugger event list. 324 */ 325void JdwpState::ResetState() { 326 /* could reset the serial numbers, but no need to */ 327 328 UnregisterAll(); 329 { 330 MutexLock mu(Thread::Current(), event_list_lock_); 331 CHECK(event_list_ == nullptr); 332 } 333 334 /* 335 * Should not have one of these in progress. If the debugger went away 336 * mid-request, though, we could see this. 337 */ 338 if (jdwp_token_owner_thread_id_ != 0) { 339 LOG(WARNING) << "Resetting state while event in progress"; 340 DCHECK(false); 341 } 342} 343 344/* 345 * Tell the JDWP thread to shut down. Frees "state". 346 */ 347JdwpState::~JdwpState() { 348 if (netState != nullptr) { 349 /* 350 * Close down the network to inspire the thread to halt. If a request is being processed, 351 * we need to wait for it to finish first. 352 */ 353 { 354 Thread* self = Thread::Current(); 355 MutexLock mu(self, shutdown_lock_); 356 while (processing_request_) { 357 VLOG(jdwp) << "JDWP command in progress: wait for it to finish ..."; 358 shutdown_cond_.Wait(self); 359 } 360 361 VLOG(jdwp) << "JDWP shutting down net..."; 362 netState->Shutdown(); 363 } 364 365 if (debug_thread_started_) { 366 run = false; 367 void* threadReturn; 368 if (pthread_join(pthread_, &threadReturn) != 0) { 369 LOG(WARNING) << "JDWP thread join failed"; 370 } 371 } 372 373 VLOG(jdwp) << "JDWP freeing netstate..."; 374 delete netState; 375 netState = nullptr; 376 } 377 CHECK(netState == nullptr); 378 379 ResetState(); 380} 381 382/* 383 * Are we talking to a debugger? 384 */ 385bool JdwpState::IsActive() { 386 return IsConnected(); 387} 388 389// Returns "false" if we encounter a connection-fatal error. 390bool JdwpState::HandlePacket() { 391 Thread* const self = Thread::Current(); 392 { 393 MutexLock mu(self, shutdown_lock_); 394 processing_request_ = true; 395 } 396 JdwpNetStateBase* netStateBase = netState; 397 CHECK(netStateBase != nullptr) << "Connection has been closed"; 398 JDWP::Request request(netStateBase->input_buffer_, netStateBase->input_count_); 399 400 ExpandBuf* pReply = expandBufAlloc(); 401 bool skip_reply = false; 402 size_t replyLength = ProcessRequest(&request, pReply, &skip_reply); 403 ssize_t cc = 0; 404 if (!skip_reply) { 405 cc = netStateBase->WritePacket(pReply, replyLength); 406 } else { 407 DCHECK_EQ(replyLength, 0U); 408 } 409 expandBufFree(pReply); 410 411 /* 412 * We processed this request and sent its reply so we can release the JDWP token. 413 */ 414 ReleaseJdwpTokenForCommand(); 415 416 if (cc != static_cast<ssize_t>(replyLength)) { 417 PLOG(ERROR) << "Failed sending reply to debugger"; 418 return false; 419 } 420 netStateBase->ConsumeBytes(request.GetLength()); 421 { 422 MutexLock mu(self, shutdown_lock_); 423 processing_request_ = false; 424 shutdown_cond_.Broadcast(self); 425 } 426 return true; 427} 428 429/* 430 * Entry point for JDWP thread. The thread was created through the VM 431 * mechanisms, so there is a java/lang/Thread associated with us. 432 */ 433static void* StartJdwpThread(void* arg) { 434 JdwpState* state = reinterpret_cast<JdwpState*>(arg); 435 CHECK(state != nullptr); 436 437 state->Run(); 438 return nullptr; 439} 440 441void JdwpState::Run() { 442 Runtime* runtime = Runtime::Current(); 443 CHECK(runtime->AttachCurrentThread("JDWP", true, runtime->GetSystemThreadGroup(), 444 !runtime->IsAotCompiler())); 445 446 VLOG(jdwp) << "JDWP: thread running"; 447 448 /* 449 * Finish initializing, then notify the creating thread that 450 * we're running. 451 */ 452 thread_ = Thread::Current(); 453 run = true; 454 455 { 456 MutexLock locker(thread_, thread_start_lock_); 457 debug_thread_started_ = true; 458 thread_start_cond_.Broadcast(thread_); 459 } 460 461 /* set the thread state to kWaitingInMainDebuggerLoop so GCs don't wait for us */ 462 CHECK_EQ(thread_->GetState(), kNative); 463 Locks::mutator_lock_->AssertNotHeld(thread_); 464 thread_->SetState(kWaitingInMainDebuggerLoop); 465 466 /* 467 * Loop forever if we're in server mode, processing connections. In 468 * non-server mode, we bail out of the thread when the debugger drops 469 * us. 470 * 471 * We broadcast a notification when a debugger attaches, after we 472 * successfully process the handshake. 473 */ 474 while (run) { 475 if (options_->server) { 476 /* 477 * Block forever, waiting for a connection. To support the 478 * "timeout=xxx" option we'll need to tweak this. 479 */ 480 if (!netState->Accept()) { 481 break; 482 } 483 } else { 484 /* 485 * If we're not acting as a server, we need to connect out to the 486 * debugger. To support the "timeout=xxx" option we need to 487 * have a timeout if the handshake reply isn't received in a 488 * reasonable amount of time. 489 */ 490 if (!netState->Establish(options_)) { 491 /* wake anybody who was waiting for us to succeed */ 492 MutexLock mu(thread_, attach_lock_); 493 debug_thread_id_ = static_cast<ObjectId>(-1); 494 attach_cond_.Broadcast(thread_); 495 break; 496 } 497 } 498 499 /* prep debug code to handle the new connection */ 500 Dbg::Connected(); 501 502 /* process requests until the debugger drops */ 503 bool first = true; 504 while (!Dbg::IsDisposed()) { 505 // sanity check -- shouldn't happen? 506 CHECK_EQ(thread_->GetState(), kWaitingInMainDebuggerLoop); 507 508 if (!netState->ProcessIncoming()) { 509 /* blocking read */ 510 break; 511 } 512 513 if (should_exit_) { 514 exit(exit_status_); 515 } 516 517 if (first && !netState->IsAwaitingHandshake()) { 518 /* handshake worked, tell the interpreter that we're active */ 519 first = false; 520 521 /* set thread ID; requires object registry to be active */ 522 { 523 ScopedObjectAccess soa(thread_); 524 debug_thread_id_ = Dbg::GetThreadSelfId(); 525 } 526 527 /* wake anybody who's waiting for us */ 528 MutexLock mu(thread_, attach_lock_); 529 attach_cond_.Broadcast(thread_); 530 } 531 } 532 533 netState->Close(); 534 535 if (ddm_is_active_) { 536 ddm_is_active_ = false; 537 538 /* broadcast the disconnect; must be in RUNNING state */ 539 ScopedObjectAccess soa(thread_); 540 Dbg::DdmDisconnected(); 541 } 542 543 { 544 ScopedObjectAccess soa(thread_); 545 546 // Release session state, e.g. remove breakpoint instructions. 547 ResetState(); 548 } 549 // Tell the rest of the runtime that the debugger is no longer around. 550 Dbg::Disconnected(); 551 552 /* if we had threads suspended, resume them now */ 553 Dbg::UndoDebuggerSuspensions(); 554 555 /* if we connected out, this was a one-shot deal */ 556 if (!options_->server) { 557 run = false; 558 } 559 } 560 561 /* back to native, for thread shutdown */ 562 CHECK_EQ(thread_->GetState(), kWaitingInMainDebuggerLoop); 563 thread_->SetState(kNative); 564 565 VLOG(jdwp) << "JDWP: thread detaching and exiting..."; 566 runtime->DetachCurrentThread(); 567} 568 569void JdwpState::NotifyDdmsActive() { 570 if (!ddm_is_active_) { 571 ddm_is_active_ = true; 572 Dbg::DdmConnected(); 573 } 574} 575 576Thread* JdwpState::GetDebugThread() { 577 return thread_; 578} 579 580/* 581 * Support routines for waitForDebugger(). 582 * 583 * We can't have a trivial "waitForDebugger" function that returns the 584 * instant the debugger connects, because we run the risk of executing code 585 * before the debugger has had a chance to configure breakpoints or issue 586 * suspend calls. It would be nice to just sit in the suspended state, but 587 * most debuggers don't expect any threads to be suspended when they attach. 588 * 589 * There's no JDWP event we can post to tell the debugger, "we've stopped, 590 * and we like it that way". We could send a fake breakpoint, which should 591 * cause the debugger to immediately send a resume, but the debugger might 592 * send the resume immediately or might throw an exception of its own upon 593 * receiving a breakpoint event that it didn't ask for. 594 * 595 * What we really want is a "wait until the debugger is done configuring 596 * stuff" event. We can approximate this with a "wait until the debugger 597 * has been idle for a brief period". 598 */ 599 600/* 601 * Return the time, in milliseconds, since the last debugger activity. 602 * 603 * Returns -1 if no debugger is attached, or 0 if we're in the middle of 604 * processing a debugger request. 605 */ 606int64_t JdwpState::LastDebuggerActivity() { 607 if (!Dbg::IsDebuggerActive()) { 608 LOG(WARNING) << "no active debugger"; 609 return -1; 610 } 611 612 int64_t last = last_activity_time_ms_.LoadSequentiallyConsistent(); 613 614 /* initializing or in the middle of something? */ 615 if (last == 0) { 616 VLOG(jdwp) << "+++ last=busy"; 617 return 0; 618 } 619 620 /* now get the current time */ 621 int64_t now = MilliTime(); 622 CHECK_GE(now, last); 623 624 VLOG(jdwp) << "+++ debugger interval=" << (now - last); 625 return now - last; 626} 627 628void JdwpState::ExitAfterReplying(int exit_status) { 629 LOG(WARNING) << "Debugger told VM to exit with status " << exit_status; 630 should_exit_ = true; 631 exit_status_ = exit_status; 632} 633 634std::ostream& operator<<(std::ostream& os, const JdwpLocation& rhs) { 635 os << "JdwpLocation[" 636 << Dbg::GetClassName(rhs.class_id) << "." << Dbg::GetMethodName(rhs.method_id) 637 << "@" << StringPrintf("%#" PRIx64, rhs.dex_pc) << " " << rhs.type_tag << "]"; 638 return os; 639} 640 641bool operator==(const JdwpLocation& lhs, const JdwpLocation& rhs) { 642 return lhs.dex_pc == rhs.dex_pc && lhs.method_id == rhs.method_id && 643 lhs.class_id == rhs.class_id && lhs.type_tag == rhs.type_tag; 644} 645 646bool operator!=(const JdwpLocation& lhs, const JdwpLocation& rhs) { 647 return !(lhs == rhs); 648} 649 650bool operator==(const JdwpOptions& lhs, const JdwpOptions& rhs) { 651 if (&lhs == &rhs) { 652 return true; 653 } 654 655 return lhs.transport == rhs.transport && 656 lhs.server == rhs.server && 657 lhs.suspend == rhs.suspend && 658 lhs.host == rhs.host && 659 lhs.port == rhs.port; 660} 661 662} // namespace JDWP 663 664} // namespace art 665