1//===-- GDBRemoteClientBaseTest.cpp ---------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8#include <future>
9
10#include "GDBRemoteTestUtils.h"
11
12#include "Plugins/Process/Utility/LinuxSignals.h"
13#include "Plugins/Process/gdb-remote/GDBRemoteClientBase.h"
14#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h"
15#include "lldb/Utility/GDBRemote.h"
16#include "llvm/ADT/STLExtras.h"
17#include "llvm/Testing/Support/Error.h"
18
19using namespace lldb_private::process_gdb_remote;
20using namespace lldb_private;
21using namespace lldb;
22typedef GDBRemoteCommunication::PacketResult PacketResult;
23
24namespace {
25
26struct MockDelegate : public GDBRemoteClientBase::ContinueDelegate {
27 std::string output;
28 std::string misc_data;
29 unsigned stop_reply_called = 0;
30 std::vector<std::string> structured_data_packets;
31
32 void HandleAsyncStdout(llvm::StringRef out) override { output += out; }
33 void HandleAsyncMisc(llvm::StringRef data) override { misc_data += data; }
34 void HandleStopReply() override { ++stop_reply_called; }
35
36 void HandleAsyncStructuredDataPacket(llvm::StringRef data) override {
37 structured_data_packets.push_back(x: std::string(data));
38 }
39};
40
41struct TestClient : public GDBRemoteClientBase {
42 TestClient() : GDBRemoteClientBase("test.client") {
43 m_send_acks = false;
44 }
45};
46
47class GDBRemoteClientBaseTest : public GDBRemoteTest {
48public:
49 void SetUp() override {
50 ASSERT_THAT_ERROR(GDBRemoteCommunication::ConnectLocally(client, server),
51 llvm::Succeeded());
52 ASSERT_EQ(TestClient::eBroadcastBitRunPacketSent,
53 listener_sp->StartListeningForEvents(
54 &client, TestClient::eBroadcastBitRunPacketSent));
55 }
56
57protected:
58 // We don't have a process to get the interrupt timeout from, so make one up.
59 static std::chrono::seconds g_timeout;
60 TestClient client;
61 MockServer server;
62 MockDelegate delegate;
63 ListenerSP listener_sp = Listener::MakeListener(name: "listener");
64
65 StateType SendCPacket(StringExtractorGDBRemote &response) {
66 return client.SendContinuePacketAndWaitForResponse(delegate, signals: LinuxSignals(),
67 payload: "c", interrupt_timeout: g_timeout,
68 response);
69 }
70
71 void WaitForRunEvent() {
72 EventSP event_sp;
73 listener_sp->GetEventForBroadcasterWithType(
74 broadcaster: &client, event_type_mask: TestClient::eBroadcastBitRunPacketSent, event_sp,
75 timeout: std::nullopt);
76 }
77};
78
79std::chrono::seconds GDBRemoteClientBaseTest::g_timeout(10);
80
81} // end anonymous namespace
82
83TEST_F(GDBRemoteClientBaseTest, SendContinueAndWait) {
84 StringExtractorGDBRemote response;
85
86 // Continue. The inferior will stop with a signal.
87 ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
88 ASSERT_EQ(eStateStopped, SendCPacket(response));
89 ASSERT_EQ("T01", response.GetStringRef());
90 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
91 ASSERT_EQ("c", response.GetStringRef());
92
93 // Continue. The inferior will exit.
94 ASSERT_EQ(PacketResult::Success, server.SendPacket("W01"));
95 ASSERT_EQ(eStateExited, SendCPacket(response));
96 ASSERT_EQ("W01", response.GetStringRef());
97 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
98 ASSERT_EQ("c", response.GetStringRef());
99
100 // Continue. The inferior will get killed.
101 ASSERT_EQ(PacketResult::Success, server.SendPacket("X01"));
102 ASSERT_EQ(eStateExited, SendCPacket(response));
103 ASSERT_EQ("X01", response.GetStringRef());
104 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
105 ASSERT_EQ("c", response.GetStringRef());
106}
107
108TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncSignal) {
109 StringExtractorGDBRemote continue_response, response;
110
111 // SendAsyncSignal should do nothing when we are not running.
112 ASSERT_FALSE(client.SendAsyncSignal(0x47, g_timeout));
113
114 // Continue. After the run packet is sent, send an async signal.
115 std::future<StateType> continue_state = std::async(
116 policy: std::launch::async, fn: [&] { return SendCPacket(response&: continue_response); });
117 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
118 ASSERT_EQ("c", response.GetStringRef());
119 WaitForRunEvent();
120
121 std::future<bool> async_result = std::async(policy: std::launch::async, fn: [&] {
122 return client.SendAsyncSignal(signo: 0x47, interrupt_timeout: g_timeout);
123 });
124
125 // First we'll get interrupted.
126 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
127 ASSERT_EQ("\x03", response.GetStringRef());
128 ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
129
130 // Then we get the signal packet.
131 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
132 ASSERT_EQ("C47", response.GetStringRef());
133 ASSERT_TRUE(async_result.get());
134
135 // And we report back a signal stop.
136 ASSERT_EQ(PacketResult::Success, server.SendPacket("T47"));
137 ASSERT_EQ(eStateStopped, continue_state.get());
138 ASSERT_EQ("T47", continue_response.GetStringRef());
139}
140
141TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncPacket) {
142 StringExtractorGDBRemote continue_response, async_response, response;
143
144 // Continue. After the run packet is sent, send an async packet.
145 std::future<StateType> continue_state = std::async(
146 policy: std::launch::async, fn: [&] { return SendCPacket(response&: continue_response); });
147 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
148 ASSERT_EQ("c", response.GetStringRef());
149 WaitForRunEvent();
150
151 // Sending without async enabled should fail.
152 ASSERT_EQ(PacketResult::ErrorSendFailed,
153 client.SendPacketAndWaitForResponse("qTest1", response));
154
155 std::future<PacketResult> async_result = std::async(policy: std::launch::async, fn: [&] {
156 return client.SendPacketAndWaitForResponse(payload: "qTest2", response&: async_response,
157 interrupt_timeout: g_timeout);
158 });
159
160 // First we'll get interrupted.
161 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
162 ASSERT_EQ("\x03", response.GetStringRef());
163 ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
164
165 // Then we get the async packet.
166 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
167 ASSERT_EQ("qTest2", response.GetStringRef());
168
169 // Send the response and receive it.
170 ASSERT_EQ(PacketResult::Success, server.SendPacket("QTest2"));
171 ASSERT_EQ(PacketResult::Success, async_result.get());
172 ASSERT_EQ("QTest2", async_response.GetStringRef());
173
174 // And we get resumed again.
175 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
176 ASSERT_EQ("c", response.GetStringRef());
177 ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
178 ASSERT_EQ(eStateStopped, continue_state.get());
179 ASSERT_EQ("T01", continue_response.GetStringRef());
180}
181
182TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt) {
183 StringExtractorGDBRemote continue_response, response;
184
185 // Interrupt should do nothing when we're not running.
186 ASSERT_FALSE(client.Interrupt(g_timeout));
187
188 // Continue. After the run packet is sent, send an interrupt.
189 std::future<StateType> continue_state = std::async(
190 policy: std::launch::async, fn: [&] { return SendCPacket(response&: continue_response); });
191 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
192 ASSERT_EQ("c", response.GetStringRef());
193 WaitForRunEvent();
194
195 std::future<bool> async_result = std::async(
196 policy: std::launch::async, fn: [&] { return client.Interrupt(interrupt_timeout: g_timeout); });
197
198 // We get interrupted.
199 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
200 ASSERT_EQ("\x03", response.GetStringRef());
201 ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
202
203 // And that's it.
204 ASSERT_EQ(eStateStopped, continue_state.get());
205 ASSERT_EQ("T13", continue_response.GetStringRef());
206 ASSERT_TRUE(async_result.get());
207}
208
209TEST_F(GDBRemoteClientBaseTest, SendContinueAndLateInterrupt) {
210 StringExtractorGDBRemote continue_response, response;
211
212 // Continue. After the run packet is sent, send an interrupt.
213 std::future<StateType> continue_state = std::async(
214 policy: std::launch::async, fn: [&] { return SendCPacket(response&: continue_response); });
215 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
216 ASSERT_EQ("c", response.GetStringRef());
217 WaitForRunEvent();
218
219 std::future<bool> async_result = std::async(
220 policy: std::launch::async, fn: [&] { return client.Interrupt(interrupt_timeout: g_timeout); });
221
222 // However, the target stops due to a different reason than the original
223 // interrupt.
224 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
225 ASSERT_EQ("\x03", response.GetStringRef());
226 ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
227 ASSERT_EQ(eStateStopped, continue_state.get());
228 ASSERT_EQ("T01", continue_response.GetStringRef());
229 ASSERT_TRUE(async_result.get());
230
231 // The subsequent continue packet should work normally.
232 ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
233 ASSERT_EQ(eStateStopped, SendCPacket(response));
234 ASSERT_EQ("T01", response.GetStringRef());
235 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
236 ASSERT_EQ("c", response.GetStringRef());
237}
238
239TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt2PacketBug) {
240 StringExtractorGDBRemote continue_response, async_response, response;
241
242 // Interrupt should do nothing when we're not running.
243 ASSERT_FALSE(client.Interrupt(g_timeout));
244
245 // Continue. After the run packet is sent, send an async signal.
246 std::future<StateType> continue_state = std::async(
247 policy: std::launch::async, fn: [&] { return SendCPacket(response&: continue_response); });
248 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
249 ASSERT_EQ("c", response.GetStringRef());
250 WaitForRunEvent();
251
252 std::future<bool> interrupt_result = std::async(
253 policy: std::launch::async, fn: [&] { return client.Interrupt(interrupt_timeout: g_timeout); });
254
255 // We get interrupted. We'll send two packets to simulate a buggy stub.
256 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
257 ASSERT_EQ("\x03", response.GetStringRef());
258 ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
259 ASSERT_EQ(PacketResult::Success, server.SendPacket("T13"));
260
261 // We should stop.
262 ASSERT_EQ(eStateStopped, continue_state.get());
263 ASSERT_EQ("T13", continue_response.GetStringRef());
264 ASSERT_TRUE(interrupt_result.get());
265
266 // Packet stream should remain synchronized.
267 std::future<PacketResult> send_result = std::async(policy: std::launch::async, fn: [&] {
268 return client.SendPacketAndWaitForResponse(payload: "qTest", response&: async_response);
269 });
270 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
271 ASSERT_EQ("qTest", response.GetStringRef());
272 ASSERT_EQ(PacketResult::Success, server.SendPacket("QTest"));
273 ASSERT_EQ(PacketResult::Success, send_result.get());
274 ASSERT_EQ("QTest", async_response.GetStringRef());
275}
276
277TEST_F(GDBRemoteClientBaseTest, SendContinueDelegateInterface) {
278 StringExtractorGDBRemote response;
279
280 // Continue. We'll have the server send a bunch of async packets before it
281 // stops.
282 ASSERT_EQ(PacketResult::Success, server.SendPacket("O4142"));
283 ASSERT_EQ(PacketResult::Success, server.SendPacket("Apro"));
284 ASSERT_EQ(PacketResult::Success, server.SendPacket("O4344"));
285 ASSERT_EQ(PacketResult::Success, server.SendPacket("Afile"));
286 ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
287 ASSERT_EQ(eStateStopped, SendCPacket(response));
288 ASSERT_EQ("T01", response.GetStringRef());
289 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
290 ASSERT_EQ("c", response.GetStringRef());
291
292 EXPECT_EQ("ABCD", delegate.output);
293 EXPECT_EQ("profile", delegate.misc_data);
294 EXPECT_EQ(1u, delegate.stop_reply_called);
295}
296
297TEST_F(GDBRemoteClientBaseTest, SendContinueDelegateStructuredDataReceipt) {
298 // Build the plain-text version of the JSON data we will have the
299 // server send.
300 const std::string json_payload =
301 "{ \"type\": \"MyFeatureType\", "
302 " \"elements\": [ \"entry1\", \"entry2\" ] }";
303 const std::string json_packet = "JSON-async:" + json_payload;
304
305 // Escape it properly for transit.
306 StreamGDBRemote stream;
307 stream.PutEscapedBytes(s: json_packet.c_str(), src_len: json_packet.length());
308 stream.Flush();
309
310 StringExtractorGDBRemote response;
311
312 // Send async structured data packet, then stop.
313 ASSERT_EQ(PacketResult::Success, server.SendPacket(stream.GetData()));
314 ASSERT_EQ(PacketResult::Success, server.SendPacket("T01"));
315 ASSERT_EQ(eStateStopped, SendCPacket(response));
316 ASSERT_EQ("T01", response.GetStringRef());
317 ASSERT_EQ(1ul, delegate.structured_data_packets.size());
318
319 // Verify the packet contents. It should have been unescaped upon packet
320 // reception.
321 ASSERT_EQ(json_packet, delegate.structured_data_packets[0]);
322}
323
324TEST_F(GDBRemoteClientBaseTest, InterruptNoResponse) {
325 StringExtractorGDBRemote continue_response, response;
326
327 // Continue. After the run packet is sent, send an interrupt.
328 std::future<StateType> continue_state = std::async(
329 policy: std::launch::async, fn: [&] { return SendCPacket(response&: continue_response); });
330 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
331 ASSERT_EQ("c", response.GetStringRef());
332 WaitForRunEvent();
333
334 std::future<bool> async_result = std::async(
335 policy: std::launch::async, fn: [&] { return client.Interrupt(interrupt_timeout: g_timeout); });
336
337 // We get interrupted, but we don't send a stop packet.
338 ASSERT_EQ(PacketResult::Success, server.GetPacket(response));
339 ASSERT_EQ("\x03", response.GetStringRef());
340
341 // The functions should still terminate (after a timeout).
342 ASSERT_TRUE(async_result.get());
343 ASSERT_EQ(eStateInvalid, continue_state.get());
344}
345
346TEST_F(GDBRemoteClientBaseTest, SendPacketAndReceiveResponseWithOutputSupport) {
347 StringExtractorGDBRemote response;
348 StreamString command_output;
349
350 ASSERT_EQ(PacketResult::Success, server.SendPacket("O"));
351 ASSERT_EQ(PacketResult::Success, server.SendPacket("O48656c6c6f2c"));
352 ASSERT_EQ(PacketResult::Success, server.SendPacket("O20"));
353 ASSERT_EQ(PacketResult::Success, server.SendPacket("O"));
354 ASSERT_EQ(PacketResult::Success, server.SendPacket("O776f726c64"));
355 ASSERT_EQ(PacketResult::Success, server.SendPacket("OK"));
356
357 PacketResult result = client.SendPacketAndReceiveResponseWithOutputSupport(
358 payload: "qRcmd,test", response, interrupt_timeout: g_timeout,
359 output_callback: [&command_output](llvm::StringRef output) { command_output << output; });
360
361 ASSERT_EQ(PacketResult::Success, result);
362 ASSERT_EQ("OK", response.GetStringRef());
363 ASSERT_EQ("Hello, world", command_output.GetString().str());
364}
365

source code of lldb/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp