• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_DEBUG_WASM_GDB_SERVER_TRANSPORT_H_
6 #define V8_DEBUG_WASM_GDB_SERVER_TRANSPORT_H_
7 
8 #include <sstream>
9 
10 #include "src/base/macros.h"
11 #include "src/debug/wasm/gdb-server/gdb-remote-util.h"
12 
13 #if _WIN32
14 #include <windows.h>
15 #include <winsock2.h>
16 
17 typedef SOCKET SocketHandle;
18 
19 #define CloseSocket closesocket
20 #define InvalidSocket INVALID_SOCKET
21 #define SocketGetLastError() WSAGetLastError()
22 static const int kErrInterrupt = WSAEINTR;
23 typedef int ssize_t;
24 typedef int socklen_t;
25 
26 #else  // _WIN32
27 
28 #include <arpa/inet.h>
29 #include <netdb.h>
30 #include <netinet/tcp.h>
31 #include <sys/select.h>
32 #include <sys/socket.h>
33 #include <unistd.h>
34 
35 typedef int SocketHandle;
36 
37 #define CloseSocket close
38 #define InvalidSocket (-1)
39 #define SocketGetLastError() errno
40 static const int kErrInterrupt = EINTR;
41 
42 #endif  // _WIN32
43 
44 namespace v8 {
45 namespace internal {
46 namespace wasm {
47 namespace gdb_server {
48 
49 class SocketTransport;
50 
51 // Acts as a factory for Transport objects bound to a specified TCP port.
52 class SocketBinding {
53  public:
54   // Wrap existing socket handle.
55   explicit SocketBinding(SocketHandle socket_handle);
56 
57   // Bind to the specified TCP port.
58   static SocketBinding Bind(uint16_t tcp_port);
59 
IsValid()60   bool IsValid() const { return socket_handle_ != InvalidSocket; }
61 
62   // Create a transport object from this socket binding
63   std::unique_ptr<SocketTransport> CreateTransport();
64 
65   // Get port the socket is bound to.
66   uint16_t GetBoundPort();
67 
68  private:
69   SocketHandle socket_handle_;
70 };
71 
72 class V8_EXPORT_PRIVATE TransportBase {
73  public:
~TransportBase()74   virtual ~TransportBase() {}
75 
76   // Waits for an incoming connection on the bound port.
77   virtual bool AcceptConnection() = 0;
78 
79   // Read {len} bytes from this transport, possibly blocking until enough data
80   // is available.
81   // {dst} must point to a buffer large enough to contain {len} bytes.
82   // Returns true on success.
83   // Returns false if the connection is closed; in that case the {dst} may have
84   // been partially overwritten.
85   virtual bool Read(char* dst, int32_t len) = 0;
86 
87   // Write {len} bytes to this transport.
88   // Return true on success, false if the connection is closed.
89   virtual bool Write(const char* src, int32_t len) = 0;
90 
91   // Return true if there is data to read.
92   virtual bool IsDataAvailable() const = 0;
93 
94   // If we are connected to a debugger, gracefully closes the connection.
95   // This should be called when a debugging session gets closed.
96   virtual void Disconnect() = 0;
97 
98   // Shuts down this transport, gracefully closing the existing connection and
99   // also closing the listening socket. This should be called when the GDB stub
100   // shuts down, when the program terminates.
101   virtual void Close() = 0;
102 
103   // Blocks waiting for one of these two events to occur:
104   // - A network event (a new packet arrives, or the connection is dropped),
105   // - A thread event is signaled (the execution stopped because of a trap or
106   // breakpoint).
107   virtual void WaitForDebugStubEvent() = 0;
108 
109   // Signal that this transport should leave an alertable wait state because
110   // the execution of the debuggee was stopped because of a trap or breakpoint.
111   virtual bool SignalThreadEvent() = 0;
112 };
113 
114 class Transport : public TransportBase {
115  public:
116   explicit Transport(SocketHandle s);
117   ~Transport() override;
118 
119   // TransportBase
120   bool Read(char* dst, int32_t len) override;
121   bool Write(const char* src, int32_t len) override;
122   bool IsDataAvailable() const override;
123   void Disconnect() override;
124   void Close() override;
125 
126   static const int kBufSize = 4096;
127 
128  protected:
129   // Copy buffered data to *dst up to len bytes and update dst and len.
130   void CopyFromBuffer(char** dst, int32_t* len);
131 
132   // Read available data from the socket. Return false on EOF or error.
133   virtual bool ReadSomeData() = 0;
134 
135   std::unique_ptr<char[]> buf_;
136   int32_t pos_;
137   int32_t size_;
138   SocketHandle handle_bind_;
139   SocketHandle handle_accept_;
140 };
141 
142 #if _WIN32
143 
144 class SocketTransport : public Transport {
145  public:
146   explicit SocketTransport(SocketHandle s);
147   ~SocketTransport() override;
148   SocketTransport(const SocketTransport&) = delete;
149   SocketTransport& operator=(const SocketTransport&) = delete;
150 
151   // TransportBase
152   bool AcceptConnection() override;
153   void Disconnect() override;
154   void WaitForDebugStubEvent() override;
155   bool SignalThreadEvent() override;
156 
157  private:
158   bool ReadSomeData() override;
159 
160   HANDLE socket_event_;
161   HANDLE faulted_thread_event_;
162 };
163 
164 #else  // _WIN32
165 
166 class SocketTransport : public Transport {
167  public:
168   explicit SocketTransport(SocketHandle s);
169   ~SocketTransport() override;
170   SocketTransport(const SocketTransport&) = delete;
171   SocketTransport& operator=(const SocketTransport&) = delete;
172 
173   // TransportBase
174   bool AcceptConnection() override;
175   void WaitForDebugStubEvent() override;
176   bool SignalThreadEvent() override;
177 
178  private:
179   bool ReadSomeData() override;
180 
181   int faulted_thread_fd_read_;
182   int faulted_thread_fd_write_;
183 };
184 
185 #endif  // _WIN32
186 
187 }  // namespace gdb_server
188 }  // namespace wasm
189 }  // namespace internal
190 }  // namespace v8
191 
192 #endif  // V8_DEBUG_WASM_GDB_SERVER_TRANSPORT_H_
193