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

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