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