11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/debug/wasm/gdb-server/gdb-server-thread.h" 61cb0ef41Sopenharmony_ci#include "src/debug/wasm/gdb-server/gdb-server.h" 71cb0ef41Sopenharmony_ci#include "src/debug/wasm/gdb-server/session.h" 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_cinamespace v8 { 101cb0ef41Sopenharmony_cinamespace internal { 111cb0ef41Sopenharmony_cinamespace wasm { 121cb0ef41Sopenharmony_cinamespace gdb_server { 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ciGdbServerThread::GdbServerThread(GdbServer* gdb_server) 151cb0ef41Sopenharmony_ci : Thread(v8::base::Thread::Options("GdbServerThread")), 161cb0ef41Sopenharmony_ci gdb_server_(gdb_server), 171cb0ef41Sopenharmony_ci start_semaphore_(0) {} 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_cibool GdbServerThread::StartAndInitialize() { 201cb0ef41Sopenharmony_ci // Executed in the Isolate thread. 211cb0ef41Sopenharmony_ci if (!Start()) { 221cb0ef41Sopenharmony_ci return false; 231cb0ef41Sopenharmony_ci } 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci // We need to make sure that {Stop} is never called before the thread has 261cb0ef41Sopenharmony_ci // completely initialized {transport_} and {target_}. Otherwise there could be 271cb0ef41Sopenharmony_ci // a race condition where in the main thread {Stop} might get called before 281cb0ef41Sopenharmony_ci // the transport is created, and then in the GDBServer thread we may have time 291cb0ef41Sopenharmony_ci // to setup the transport and block on accept() before the main thread blocks 301cb0ef41Sopenharmony_ci // on joining the thread. 311cb0ef41Sopenharmony_ci // The small performance hit caused by this Wait should be negligeable because 321cb0ef41Sopenharmony_ci // this operation happensat most once per process and only when the 331cb0ef41Sopenharmony_ci // --wasm-gdb-remote flag is set. 341cb0ef41Sopenharmony_ci start_semaphore_.Wait(); 351cb0ef41Sopenharmony_ci return !!target_; 361cb0ef41Sopenharmony_ci} 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_civoid GdbServerThread::CleanupThread() { 391cb0ef41Sopenharmony_ci // Executed in the GdbServer thread. 401cb0ef41Sopenharmony_ci v8::base::MutexGuard guard(&mutex_); 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ci target_ = nullptr; 431cb0ef41Sopenharmony_ci transport_ = nullptr; 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ci#if _WIN32 461cb0ef41Sopenharmony_ci ::WSACleanup(); 471cb0ef41Sopenharmony_ci#endif 481cb0ef41Sopenharmony_ci} 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_civoid GdbServerThread::Run() { 511cb0ef41Sopenharmony_ci // Executed in the GdbServer thread. 521cb0ef41Sopenharmony_ci#ifdef _WIN32 531cb0ef41Sopenharmony_ci // Initialize Winsock 541cb0ef41Sopenharmony_ci WSADATA wsaData; 551cb0ef41Sopenharmony_ci int iResult = ::WSAStartup(MAKEWORD(2, 2), &wsaData); 561cb0ef41Sopenharmony_ci if (iResult != 0) { 571cb0ef41Sopenharmony_ci TRACE_GDB_REMOTE("GdbServerThread::Run: WSAStartup failed\n"); 581cb0ef41Sopenharmony_ci return; 591cb0ef41Sopenharmony_ci } 601cb0ef41Sopenharmony_ci#endif 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci // If the default port is not available, try any port. 631cb0ef41Sopenharmony_ci SocketBinding socket_binding = SocketBinding::Bind(FLAG_wasm_gdb_remote_port); 641cb0ef41Sopenharmony_ci if (!socket_binding.IsValid()) { 651cb0ef41Sopenharmony_ci socket_binding = SocketBinding::Bind(0); 661cb0ef41Sopenharmony_ci } 671cb0ef41Sopenharmony_ci if (!socket_binding.IsValid()) { 681cb0ef41Sopenharmony_ci TRACE_GDB_REMOTE("GdbServerThread::Run: Failed to bind any TCP port\n"); 691cb0ef41Sopenharmony_ci return; 701cb0ef41Sopenharmony_ci } 711cb0ef41Sopenharmony_ci TRACE_GDB_REMOTE("gdb-remote(%d) : Connect GDB with 'target remote :%d\n", 721cb0ef41Sopenharmony_ci __LINE__, socket_binding.GetBoundPort()); 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci transport_ = socket_binding.CreateTransport(); 751cb0ef41Sopenharmony_ci target_ = std::make_unique<Target>(gdb_server_); 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci // Here we have completed the initialization, and the thread that called 781cb0ef41Sopenharmony_ci // {StartAndInitialize} may resume execution. 791cb0ef41Sopenharmony_ci start_semaphore_.Signal(); 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci while (!target_->IsTerminated()) { 821cb0ef41Sopenharmony_ci // Wait for incoming connections. 831cb0ef41Sopenharmony_ci if (!transport_->AcceptConnection()) { 841cb0ef41Sopenharmony_ci continue; 851cb0ef41Sopenharmony_ci } 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci // Create a new session for this connection 881cb0ef41Sopenharmony_ci Session session(transport_.get()); 891cb0ef41Sopenharmony_ci TRACE_GDB_REMOTE("GdbServerThread: Connected\n"); 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_ci // Run this session for as long as it lasts 921cb0ef41Sopenharmony_ci target_->Run(&session); 931cb0ef41Sopenharmony_ci } 941cb0ef41Sopenharmony_ci CleanupThread(); 951cb0ef41Sopenharmony_ci} 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_civoid GdbServerThread::Stop() { 981cb0ef41Sopenharmony_ci // Executed in the Isolate thread. 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci // Synchronized, becauses {Stop} might be called while {Run} is still 1011cb0ef41Sopenharmony_ci // initializing {transport_} and {target_}. If this happens and the thread is 1021cb0ef41Sopenharmony_ci // blocked waiting for an incoming connection or GdbServer for incoming 1031cb0ef41Sopenharmony_ci // packets, it will unblocked when {transport_} is closed. 1041cb0ef41Sopenharmony_ci v8::base::MutexGuard guard(&mutex_); 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ci if (target_) { 1071cb0ef41Sopenharmony_ci target_->Terminate(); 1081cb0ef41Sopenharmony_ci } 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci if (transport_) { 1111cb0ef41Sopenharmony_ci transport_->Close(); 1121cb0ef41Sopenharmony_ci } 1131cb0ef41Sopenharmony_ci} 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_ci} // namespace gdb_server 1161cb0ef41Sopenharmony_ci} // namespace wasm 1171cb0ef41Sopenharmony_ci} // namespace internal 1181cb0ef41Sopenharmony_ci} // namespace v8 119