blob: 7e51a3879abe8ce5ad7bc610d9fdadb65a9996bd [file] [log] [blame]
Pavel Labath015f17d2017-06-06 13:40:18 +00001//===-- TestClient.cpp ------------------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Pavel Labath015f17d2017-06-06 13:40:18 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "TestClient.h"
Pavel Labath015f17d2017-06-06 13:40:18 +000010#include "lldb/Host/HostInfo.h"
11#include "lldb/Host/common/TCPSocket.h"
12#include "lldb/Host/posix/ConnectionFileDescriptorPosix.h"
Pavel Labath145d95c2018-04-17 18:53:35 +000013#include "lldb/Utility/Args.h"
Pavel Labath015f17d2017-06-06 13:40:18 +000014#include "llvm/ADT/StringExtras.h"
Pavel Labathc596e902017-10-17 16:28:28 +000015#include "llvm/Support/Path.h"
Pavel Labath671d3e62017-12-15 13:56:22 +000016#include "llvm/Testing/Support/Error.h"
Pavel Labath015f17d2017-06-06 13:40:18 +000017#include "gtest/gtest.h"
18#include <cstdlib>
19#include <future>
20#include <sstream>
21#include <string>
22
23using namespace lldb;
24using namespace lldb_private;
25using namespace llvm;
Pavel Labatha1181312018-02-09 09:40:03 +000026using namespace llgs_tests;
Pavel Labathc596e902017-10-17 16:28:28 +000027
Aaron Smith5146a9e2019-08-13 22:18:01 +000028#ifdef SendMessage
29#undef SendMessage
30#endif
31
Pavel Labath671d3e62017-12-15 13:56:22 +000032TestClient::TestClient(std::unique_ptr<Connection> Conn) {
33 SetConnection(Conn.release());
Pavel Labath691d1342018-04-23 11:22:44 +000034 SetPacketTimeout(std::chrono::seconds(10));
Pavel Labath671d3e62017-12-15 13:56:22 +000035}
Pavel Labath015f17d2017-06-06 13:40:18 +000036
Pavel Labath671d3e62017-12-15 13:56:22 +000037TestClient::~TestClient() {
Pavel Labathd8b3c1a2017-12-18 09:44:29 +000038 if (!IsConnected())
39 return;
40
Pavel Labath5a841232018-03-28 10:19:10 +000041 EXPECT_THAT_ERROR(SendMessage("k"), Succeeded());
Pavel Labath671d3e62017-12-15 13:56:22 +000042}
43
Pavel Labathd2f36c82018-04-30 14:30:02 +000044Error TestClient::initializeConnection() {
45 if (SendAck() == 0)
46 return make_error<StringError>("Sending initial ACK failed.",
47 inconvertibleErrorCode());
48
49 if (Error E = SendMessage("QStartNoAckMode"))
50 return E;
51
52 m_send_acks = false;
53 return Error::success();
54}
55
Pavel Labath671d3e62017-12-15 13:56:22 +000056Expected<std::unique_ptr<TestClient>> TestClient::launch(StringRef Log) {
57 return launch(Log, {});
58}
59
60Expected<std::unique_ptr<TestClient>> TestClient::launch(StringRef Log, ArrayRef<StringRef> InferiorArgs) {
Pavel Labathdeb45f22017-12-22 11:09:21 +000061 return launchCustom(Log, {}, InferiorArgs);
62}
63
64Expected<std::unique_ptr<TestClient>> TestClient::launchCustom(StringRef Log, ArrayRef<StringRef> ServerArgs, ArrayRef<StringRef> InferiorArgs) {
Pavel Labath015f17d2017-06-06 13:40:18 +000065 const ArchSpec &arch_spec = HostInfo::GetArchitecture();
66 Args args;
67 args.AppendArgument(LLDB_SERVER);
Pavel Labath671d3e62017-12-15 13:56:22 +000068 if (IsLldbServer())
Pavel Labathc596e902017-10-17 16:28:28 +000069 args.AppendArgument("gdbserver");
Pavel Labath015f17d2017-06-06 13:40:18 +000070 args.AppendArgument("--reverse-connect");
Pavel Labath671d3e62017-12-15 13:56:22 +000071
72 if (!Log.empty()) {
73 args.AppendArgument(("--log-file=" + Log).str());
74 if (IsLldbServer())
75 args.AppendArgument("--log-channels=gdb-remote packets");
76 else
77 args.AppendArgument("--log-flags=0x800000");
78 }
Pavel Labath015f17d2017-06-06 13:40:18 +000079
Pavel Labath1ebc85f2017-11-09 15:45:09 +000080 Status status;
Pavel Labath015f17d2017-06-06 13:40:18 +000081 TCPSocket listen_socket(true, false);
Pavel Labath1ebc85f2017-11-09 15:45:09 +000082 status = listen_socket.Listen("127.0.0.1:0", 5);
83 if (status.Fail())
84 return status.ToError();
Pavel Labath015f17d2017-06-06 13:40:18 +000085
Pavel Labath671d3e62017-12-15 13:56:22 +000086 args.AppendArgument(
Michal Gornyf6e55942019-02-12 18:09:00 +000087 ("127.0.0.1:" + Twine(listen_socket.GetLocalPortNumber())).str());
Pavel Labath015f17d2017-06-06 13:40:18 +000088
Pavel Labathdeb45f22017-12-22 11:09:21 +000089 for (StringRef arg : ServerArgs)
90 args.AppendArgument(arg);
91
Pavel Labath671d3e62017-12-15 13:56:22 +000092 if (!InferiorArgs.empty()) {
93 args.AppendArgument("--");
94 for (StringRef arg : InferiorArgs)
95 args.AppendArgument(arg);
96 }
Pavel Labath015f17d2017-06-06 13:40:18 +000097
Pavel Labath671d3e62017-12-15 13:56:22 +000098 ProcessLaunchInfo Info;
99 Info.SetArchitecture(arch_spec);
100 Info.SetArguments(args, true);
Pavel Labath62930e52018-01-10 11:57:31 +0000101 Info.GetEnvironment() = Host::GetEnvironment();
Pavel Labath245dd2e2018-05-15 13:42:26 +0000102 // TODO: Use this callback to detect botched launches. If lldb-server does not
103 // start, we can print a nice error message here instead of hanging in
104 // Accept().
105 Info.SetMonitorProcessCallback(&ProcessLaunchInfo::NoOpMonitorCallback,
106 false);
Pavel Labath11e59172017-12-18 14:31:39 +0000107
Pavel Labath671d3e62017-12-15 13:56:22 +0000108 status = Host::LaunchProcess(Info);
Pavel Labath1ebc85f2017-11-09 15:45:09 +0000109 if (status.Fail())
110 return status.ToError();
Pavel Labath015f17d2017-06-06 13:40:18 +0000111
Pavel Labath015f17d2017-06-06 13:40:18 +0000112 Socket *accept_socket;
113 listen_socket.Accept(accept_socket);
Jonas Devliegherea8f3ae72019-08-14 22:19:23 +0000114 auto Conn = std::make_unique<ConnectionFileDescriptor>(accept_socket);
Pavel Labath11e59172017-12-18 14:31:39 +0000115 auto Client = std::unique_ptr<TestClient>(new TestClient(std::move(Conn)));
116
Pavel Labathd2f36c82018-04-30 14:30:02 +0000117 if (Error E = Client->initializeConnection())
118 return std::move(E);
119
Pavel Labath11e59172017-12-18 14:31:39 +0000120 if (!InferiorArgs.empty()) {
Pavel Labatha1181312018-02-09 09:40:03 +0000121 if (Error E = Client->queryProcess())
Pavel Labath11e59172017-12-18 14:31:39 +0000122 return std::move(E);
123 }
124
125 return std::move(Client);
Pavel Labath015f17d2017-06-06 13:40:18 +0000126}
127
Pavel Labath1ebc85f2017-11-09 15:45:09 +0000128Error TestClient::SetInferior(llvm::ArrayRef<std::string> inferior_args) {
Pavel Labath62930e52018-01-10 11:57:31 +0000129 if (SendEnvironment(Host::GetEnvironment()) != 0) {
130 return make_error<StringError>("Failed to set launch environment",
131 inconvertibleErrorCode());
Pavel Labath7b9b30a2017-10-20 22:39:18 +0000132 }
Pavel Labath015f17d2017-06-06 13:40:18 +0000133 std::stringstream command;
134 command << "A";
135 for (size_t i = 0; i < inferior_args.size(); i++) {
136 if (i > 0)
137 command << ',';
138 std::string hex_encoded = toHex(inferior_args[i]);
139 command << hex_encoded.size() << ',' << i << ',' << hex_encoded;
140 }
141
Pavel Labath1ebc85f2017-11-09 15:45:09 +0000142 if (Error E = SendMessage(command.str()))
143 return E;
144 if (Error E = SendMessage("qLaunchSuccess"))
145 return E;
Pavel Labatha1181312018-02-09 09:40:03 +0000146 if (Error E = queryProcess())
Pavel Labath1ebc85f2017-11-09 15:45:09 +0000147 return E;
Pavel Labath1ebc85f2017-11-09 15:45:09 +0000148 return Error::success();
Pavel Labath015f17d2017-06-06 13:40:18 +0000149}
150
Pavel Labath1ebc85f2017-11-09 15:45:09 +0000151Error TestClient::ListThreadsInStopReply() {
Pavel Labath015f17d2017-06-06 13:40:18 +0000152 return SendMessage("QListThreadsInStopReply");
153}
154
Pavel Labath1ebc85f2017-11-09 15:45:09 +0000155Error TestClient::SetBreakpoint(unsigned long address) {
156 return SendMessage(formatv("Z0,{0:x-},1", address).str());
Pavel Labath015f17d2017-06-06 13:40:18 +0000157}
158
Pavel Labath1ebc85f2017-11-09 15:45:09 +0000159Error TestClient::ContinueAll() { return Continue("vCont;c"); }
Pavel Labath015f17d2017-06-06 13:40:18 +0000160
Pavel Labath1ebc85f2017-11-09 15:45:09 +0000161Error TestClient::ContinueThread(unsigned long thread_id) {
Pavel Labath015f17d2017-06-06 13:40:18 +0000162 return Continue(formatv("vCont;c:{0:x-}", thread_id).str());
163}
164
Pavel Labatha1181312018-02-09 09:40:03 +0000165const llgs_tests::ProcessInfo &TestClient::GetProcessInfo() {
166 return *m_process_info;
167}
Pavel Labath015f17d2017-06-06 13:40:18 +0000168
Pavel Labath9a9556f2018-02-19 15:42:48 +0000169Expected<JThreadsInfo> TestClient::GetJThreadsInfo() {
170 return SendMessage<JThreadsInfo>("jThreadsInfo", m_register_infos);
Pavel Labath015f17d2017-06-06 13:40:18 +0000171}
172
173const StopReply &TestClient::GetLatestStopReply() {
Pavel Labath93a582c2017-12-15 15:19:45 +0000174 assert(m_stop_reply);
175 return *m_stop_reply;
Pavel Labath015f17d2017-06-06 13:40:18 +0000176}
177
Pavel Labath1ebc85f2017-11-09 15:45:09 +0000178Error TestClient::SendMessage(StringRef message) {
Pavel Labath015f17d2017-06-06 13:40:18 +0000179 std::string dummy_string;
180 return SendMessage(message, dummy_string);
181}
182
Pavel Labath1ebc85f2017-11-09 15:45:09 +0000183Error TestClient::SendMessage(StringRef message, std::string &response_string) {
184 if (Error E = SendMessage(message, response_string, PacketResult::Success))
185 return E;
Pavel Labatha70512a2018-04-11 13:30:54 +0000186 StringExtractorGDBRemote Extractor(response_string);
187 if (Extractor.IsErrorResponse())
188 return Extractor.GetStatus().ToError();
Pavel Labath1ebc85f2017-11-09 15:45:09 +0000189 return Error::success();
Pavel Labath015f17d2017-06-06 13:40:18 +0000190}
191
Pavel Labath1ebc85f2017-11-09 15:45:09 +0000192Error TestClient::SendMessage(StringRef message, std::string &response_string,
193 PacketResult expected_result) {
Pavel Labath015f17d2017-06-06 13:40:18 +0000194 StringExtractorGDBRemote response;
195 GTEST_LOG_(INFO) << "Send Packet: " << message.str();
196 PacketResult result = SendPacketAndWaitForResponse(message, response, false);
197 response.GetEscapedBinaryData(response_string);
198 GTEST_LOG_(INFO) << "Read Packet: " << response_string;
Pavel Labath1ebc85f2017-11-09 15:45:09 +0000199 if (result != expected_result)
200 return make_error<StringError>(
201 formatv("Error sending message `{0}`: {1}", message, result).str(),
202 inconvertibleErrorCode());
Pavel Labath015f17d2017-06-06 13:40:18 +0000203
Pavel Labath1ebc85f2017-11-09 15:45:09 +0000204 return Error::success();
Pavel Labath015f17d2017-06-06 13:40:18 +0000205}
206
207unsigned int TestClient::GetPcRegisterId() {
Pavel Labatha1181312018-02-09 09:40:03 +0000208 assert(m_pc_register != LLDB_INVALID_REGNUM);
Pavel Labath015f17d2017-06-06 13:40:18 +0000209 return m_pc_register;
210}
211
Pavel Labatha1181312018-02-09 09:40:03 +0000212Error TestClient::qProcessInfo() {
213 m_process_info = None;
214 auto InfoOr = SendMessage<ProcessInfo>("qProcessInfo");
215 if (!InfoOr)
216 return InfoOr.takeError();
217 m_process_info = std::move(*InfoOr);
218 return Error::success();
219}
220
221Error TestClient::qRegisterInfos() {
222 for (unsigned int Reg = 0;; ++Reg) {
223 std::string Message = formatv("qRegisterInfo{0:x-}", Reg).str();
224 Expected<RegisterInfo> InfoOr = SendMessage<RegisterInfoParser>(Message);
225 if (!InfoOr) {
226 consumeError(InfoOr.takeError());
227 break;
228 }
229 m_register_infos.emplace_back(std::move(*InfoOr));
230 if (m_register_infos[Reg].kinds[eRegisterKindGeneric] ==
231 LLDB_REGNUM_GENERIC_PC)
232 m_pc_register = Reg;
233 }
234 if (m_pc_register == LLDB_INVALID_REGNUM)
235 return make_parsing_error("qRegisterInfo: generic");
236 return Error::success();
237}
238
239Error TestClient::queryProcess() {
240 if (Error E = qProcessInfo())
Pavel Labath671d3e62017-12-15 13:56:22 +0000241 return E;
Pavel Labatha1181312018-02-09 09:40:03 +0000242 if (Error E = qRegisterInfos())
243 return E;
Pavel Labath671d3e62017-12-15 13:56:22 +0000244 return Error::success();
245}
246
Pavel Labath1ebc85f2017-11-09 15:45:09 +0000247Error TestClient::Continue(StringRef message) {
248 assert(m_process_info.hasValue());
Pavel Labath015f17d2017-06-06 13:40:18 +0000249
Pavel Labathcdf7a9f2018-03-04 02:12:18 +0000250 auto StopReplyOr = SendMessage<StopReply>(
251 message, m_process_info->GetEndian(), m_register_infos);
252 if (!StopReplyOr)
253 return StopReplyOr.takeError();
Pavel Labath015f17d2017-06-06 13:40:18 +0000254
Pavel Labathcdf7a9f2018-03-04 02:12:18 +0000255 m_stop_reply = std::move(*StopReplyOr);
Pavel Labathd8b3c1a2017-12-18 09:44:29 +0000256 if (!isa<StopReplyStop>(m_stop_reply)) {
257 StringExtractorGDBRemote R;
258 PacketResult result = ReadPacket(R, GetPacketTimeout(), false);
259 if (result != PacketResult::ErrorDisconnected) {
260 return make_error<StringError>(
Pavel Labathcdf7a9f2018-03-04 02:12:18 +0000261 formatv("Expected connection close after sending {0}. Got {1}/{2} "
Pavel Labathd8b3c1a2017-12-18 09:44:29 +0000262 "instead.",
Pavel Labathcdf7a9f2018-03-04 02:12:18 +0000263 message, result, R.GetStringRef())
Pavel Labathd8b3c1a2017-12-18 09:44:29 +0000264 .str(),
265 inconvertibleErrorCode());
266 }
267 }
Pavel Labath1ebc85f2017-11-09 15:45:09 +0000268 return Error::success();
Pavel Labath015f17d2017-06-06 13:40:18 +0000269}