xref: /llvm-project/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp (revision b9c1b51e45b845debb76d8658edabca70ca56079)
1 //===-- GDBRemoteCommunicationClientTest.cpp --------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #if defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0)
11 // Workaround for MSVC standard library bug, which fails to include <thread>
12 // when
13 // exceptions are disabled.
14 #include <eh.h>
15 #endif
16 #include <future>
17 
18 #include "GDBRemoteTestUtils.h"
19 #include "gtest/gtest.h"
20 
21 #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h"
22 #include "lldb/Core/DataBuffer.h"
23 
24 #include "llvm/ADT/ArrayRef.h"
25 
26 using namespace lldb_private::process_gdb_remote;
27 using namespace lldb_private;
28 using namespace lldb;
29 
30 namespace {
31 
32 typedef GDBRemoteCommunication::PacketResult PacketResult;
33 
34 struct TestClient : public GDBRemoteCommunicationClient {
35   TestClient() { m_send_acks = false; }
36 };
37 
38 void Handle_QThreadSuffixSupported(MockServer &server, bool supported) {
39   StringExtractorGDBRemote request;
40   ASSERT_EQ(PacketResult::Success, server.GetPacket(request));
41   ASSERT_EQ("QThreadSuffixSupported", request.GetStringRef());
42   if (supported)
43     ASSERT_EQ(PacketResult::Success, server.SendOKResponse());
44   else
45     ASSERT_EQ(PacketResult::Success, server.SendUnimplementedResponse(nullptr));
46 }
47 
48 void HandlePacket(MockServer &server, llvm::StringRef expected,
49                   llvm::StringRef response) {
50   StringExtractorGDBRemote request;
51   ASSERT_EQ(PacketResult::Success, server.GetPacket(request));
52   ASSERT_EQ(expected, request.GetStringRef());
53   ASSERT_EQ(PacketResult::Success, server.SendPacket(response));
54 }
55 
56 uint8_t all_registers[] = {'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
57                            'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'};
58 std::string all_registers_hex = "404142434445464748494a4b4c4d4e4f";
59 uint8_t one_register[] = {'A', 'B', 'C', 'D'};
60 std::string one_register_hex = "41424344";
61 
62 } // end anonymous namespace
63 
64 class GDBRemoteCommunicationClientTest : public GDBRemoteTest {};
65 
66 TEST_F(GDBRemoteCommunicationClientTest, WriteRegister) {
67   TestClient client;
68   MockServer server;
69   Connect(client, server);
70   if (HasFailure())
71     return;
72 
73   const lldb::tid_t tid = 0x47;
74   const uint32_t reg_num = 4;
75   std::future<bool> write_result = std::async(std::launch::async, [&] {
76     return client.WriteRegister(tid, reg_num, one_register);
77   });
78 
79   Handle_QThreadSuffixSupported(server, true);
80 
81   HandlePacket(server, "P4=" + one_register_hex + ";thread:0047;", "OK");
82   ASSERT_TRUE(write_result.get());
83 
84   write_result = std::async(std::launch::async, [&] {
85     return client.WriteAllRegisters(tid, all_registers);
86   });
87 
88   HandlePacket(server, "G" + all_registers_hex + ";thread:0047;", "OK");
89   ASSERT_TRUE(write_result.get());
90 }
91 
92 TEST_F(GDBRemoteCommunicationClientTest, WriteRegisterNoSuffix) {
93   TestClient client;
94   MockServer server;
95   Connect(client, server);
96   if (HasFailure())
97     return;
98 
99   const lldb::tid_t tid = 0x47;
100   const uint32_t reg_num = 4;
101   std::future<bool> write_result = std::async(std::launch::async, [&] {
102     return client.WriteRegister(tid, reg_num, one_register);
103   });
104 
105   Handle_QThreadSuffixSupported(server, false);
106   HandlePacket(server, "Hg47", "OK");
107   HandlePacket(server, "P4=" + one_register_hex, "OK");
108   ASSERT_TRUE(write_result.get());
109 
110   write_result = std::async(std::launch::async, [&] {
111     return client.WriteAllRegisters(tid, all_registers);
112   });
113 
114   HandlePacket(server, "G" + all_registers_hex, "OK");
115   ASSERT_TRUE(write_result.get());
116 }
117 
118 TEST_F(GDBRemoteCommunicationClientTest, ReadRegister) {
119   TestClient client;
120   MockServer server;
121   Connect(client, server);
122   if (HasFailure())
123     return;
124 
125   const lldb::tid_t tid = 0x47;
126   const uint32_t reg_num = 4;
127   std::future<bool> async_result = std::async(
128       std::launch::async, [&] { return client.GetpPacketSupported(tid); });
129   Handle_QThreadSuffixSupported(server, true);
130   HandlePacket(server, "p0;thread:0047;", one_register_hex);
131   ASSERT_TRUE(async_result.get());
132 
133   std::future<DataBufferSP> read_result = std::async(
134       std::launch::async, [&] { return client.ReadRegister(tid, reg_num); });
135   HandlePacket(server, "p4;thread:0047;", "41424344");
136   auto buffer_sp = read_result.get();
137   ASSERT_TRUE(bool(buffer_sp));
138   ASSERT_EQ(0,
139             memcmp(buffer_sp->GetBytes(), one_register, sizeof one_register));
140 
141   read_result = std::async(std::launch::async,
142                            [&] { return client.ReadAllRegisters(tid); });
143   HandlePacket(server, "g;thread:0047;", all_registers_hex);
144   buffer_sp = read_result.get();
145   ASSERT_TRUE(bool(buffer_sp));
146   ASSERT_EQ(0,
147             memcmp(buffer_sp->GetBytes(), all_registers, sizeof all_registers));
148 }
149 
150 TEST_F(GDBRemoteCommunicationClientTest, SaveRestoreRegistersNoSuffix) {
151   TestClient client;
152   MockServer server;
153   Connect(client, server);
154   if (HasFailure())
155     return;
156 
157   const lldb::tid_t tid = 0x47;
158   uint32_t save_id;
159   std::future<bool> async_result = std::async(std::launch::async, [&] {
160     return client.SaveRegisterState(tid, save_id);
161   });
162   Handle_QThreadSuffixSupported(server, false);
163   HandlePacket(server, "Hg47", "OK");
164   HandlePacket(server, "QSaveRegisterState", "1");
165   ASSERT_TRUE(async_result.get());
166   EXPECT_EQ(1u, save_id);
167 
168   async_result = std::async(std::launch::async, [&] {
169     return client.RestoreRegisterState(tid, save_id);
170   });
171   HandlePacket(server, "QRestoreRegisterState:1", "OK");
172   ASSERT_TRUE(async_result.get());
173 }
174 
175 TEST_F(GDBRemoteCommunicationClientTest, SyncThreadState) {
176   TestClient client;
177   MockServer server;
178   Connect(client, server);
179   if (HasFailure())
180     return;
181 
182   const lldb::tid_t tid = 0x47;
183   std::future<bool> async_result = std::async(
184       std::launch::async, [&] { return client.SyncThreadState(tid); });
185   HandlePacket(server, "qSyncThreadStateSupported", "OK");
186   HandlePacket(server, "QSyncThreadState:0047;", "OK");
187   ASSERT_TRUE(async_result.get());
188 }
189