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