1 //===-- TestClient.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 #include "TestClient.h" 11 #include "lldb/Host/HostInfo.h" 12 #include "lldb/Host/common/TCPSocket.h" 13 #include "lldb/Host/posix/ConnectionFileDescriptorPosix.h" 14 #include "lldb/Target/ProcessLaunchInfo.h" 15 #include "lldb/Utility/Args.h" 16 #include "llvm/ADT/StringExtras.h" 17 #include "llvm/Support/Path.h" 18 #include "llvm/Testing/Support/Error.h" 19 #include "gtest/gtest.h" 20 #include <cstdlib> 21 #include <future> 22 #include <sstream> 23 #include <string> 24 25 using namespace lldb; 26 using namespace lldb_private; 27 using namespace llvm; 28 using namespace llgs_tests; 29 30 TestClient::TestClient(std::unique_ptr<Connection> Conn) { 31 SetConnection(Conn.release()); 32 SetPacketTimeout(std::chrono::seconds(10)); 33 } 34 35 TestClient::~TestClient() { 36 if (!IsConnected()) 37 return; 38 39 EXPECT_THAT_ERROR(SendMessage("k"), Succeeded()); 40 } 41 42 Error TestClient::initializeConnection() { 43 if (SendAck() == 0) 44 return make_error<StringError>("Sending initial ACK failed.", 45 inconvertibleErrorCode()); 46 47 if (Error E = SendMessage("QStartNoAckMode")) 48 return E; 49 50 m_send_acks = false; 51 return Error::success(); 52 } 53 54 Expected<std::unique_ptr<TestClient>> TestClient::launch(StringRef Log) { 55 return launch(Log, {}); 56 } 57 58 Expected<std::unique_ptr<TestClient>> TestClient::launch(StringRef Log, ArrayRef<StringRef> InferiorArgs) { 59 return launchCustom(Log, {}, InferiorArgs); 60 } 61 62 Expected<std::unique_ptr<TestClient>> TestClient::launchCustom(StringRef Log, ArrayRef<StringRef> ServerArgs, ArrayRef<StringRef> InferiorArgs) { 63 const ArchSpec &arch_spec = HostInfo::GetArchitecture(); 64 Args args; 65 args.AppendArgument(LLDB_SERVER); 66 if (IsLldbServer()) 67 args.AppendArgument("gdbserver"); 68 args.AppendArgument("--reverse-connect"); 69 70 if (!Log.empty()) { 71 args.AppendArgument(("--log-file=" + Log).str()); 72 if (IsLldbServer()) 73 args.AppendArgument("--log-channels=gdb-remote packets"); 74 else 75 args.AppendArgument("--log-flags=0x800000"); 76 } 77 78 Status status; 79 TCPSocket listen_socket(true, false); 80 status = listen_socket.Listen("127.0.0.1:0", 5); 81 if (status.Fail()) 82 return status.ToError(); 83 84 args.AppendArgument( 85 ("localhost:" + Twine(listen_socket.GetLocalPortNumber())).str()); 86 87 for (StringRef arg : ServerArgs) 88 args.AppendArgument(arg); 89 90 if (!InferiorArgs.empty()) { 91 args.AppendArgument("--"); 92 for (StringRef arg : InferiorArgs) 93 args.AppendArgument(arg); 94 } 95 96 ProcessLaunchInfo Info; 97 Info.SetArchitecture(arch_spec); 98 Info.SetArguments(args, true); 99 Info.GetEnvironment() = Host::GetEnvironment(); 100 // TODO: Use this callback to detect botched launches. If lldb-server does not 101 // start, we can print a nice error message here instead of hanging in 102 // Accept(). 103 Info.SetMonitorProcessCallback(&ProcessLaunchInfo::NoOpMonitorCallback, 104 false); 105 106 status = Host::LaunchProcess(Info); 107 if (status.Fail()) 108 return status.ToError(); 109 110 Socket *accept_socket; 111 listen_socket.Accept(accept_socket); 112 auto Conn = llvm::make_unique<ConnectionFileDescriptor>(accept_socket); 113 auto Client = std::unique_ptr<TestClient>(new TestClient(std::move(Conn))); 114 115 if (Error E = Client->initializeConnection()) 116 return std::move(E); 117 118 if (!InferiorArgs.empty()) { 119 if (Error E = Client->queryProcess()) 120 return std::move(E); 121 } 122 123 return std::move(Client); 124 } 125 126 Error TestClient::SetInferior(llvm::ArrayRef<std::string> inferior_args) { 127 if (SendEnvironment(Host::GetEnvironment()) != 0) { 128 return make_error<StringError>("Failed to set launch environment", 129 inconvertibleErrorCode()); 130 } 131 std::stringstream command; 132 command << "A"; 133 for (size_t i = 0; i < inferior_args.size(); i++) { 134 if (i > 0) 135 command << ','; 136 std::string hex_encoded = toHex(inferior_args[i]); 137 command << hex_encoded.size() << ',' << i << ',' << hex_encoded; 138 } 139 140 if (Error E = SendMessage(command.str())) 141 return E; 142 if (Error E = SendMessage("qLaunchSuccess")) 143 return E; 144 if (Error E = queryProcess()) 145 return E; 146 return Error::success(); 147 } 148 149 Error TestClient::ListThreadsInStopReply() { 150 return SendMessage("QListThreadsInStopReply"); 151 } 152 153 Error TestClient::SetBreakpoint(unsigned long address) { 154 return SendMessage(formatv("Z0,{0:x-},1", address).str()); 155 } 156 157 Error TestClient::ContinueAll() { return Continue("vCont;c"); } 158 159 Error TestClient::ContinueThread(unsigned long thread_id) { 160 return Continue(formatv("vCont;c:{0:x-}", thread_id).str()); 161 } 162 163 const llgs_tests::ProcessInfo &TestClient::GetProcessInfo() { 164 return *m_process_info; 165 } 166 167 Expected<JThreadsInfo> TestClient::GetJThreadsInfo() { 168 return SendMessage<JThreadsInfo>("jThreadsInfo", m_register_infos); 169 } 170 171 const StopReply &TestClient::GetLatestStopReply() { 172 assert(m_stop_reply); 173 return *m_stop_reply; 174 } 175 176 Error TestClient::SendMessage(StringRef message) { 177 std::string dummy_string; 178 return SendMessage(message, dummy_string); 179 } 180 181 Error TestClient::SendMessage(StringRef message, std::string &response_string) { 182 if (Error E = SendMessage(message, response_string, PacketResult::Success)) 183 return E; 184 StringExtractorGDBRemote Extractor(response_string); 185 if (Extractor.IsErrorResponse()) 186 return Extractor.GetStatus().ToError(); 187 return Error::success(); 188 } 189 190 Error TestClient::SendMessage(StringRef message, std::string &response_string, 191 PacketResult expected_result) { 192 StringExtractorGDBRemote response; 193 GTEST_LOG_(INFO) << "Send Packet: " << message.str(); 194 PacketResult result = SendPacketAndWaitForResponse(message, response, false); 195 response.GetEscapedBinaryData(response_string); 196 GTEST_LOG_(INFO) << "Read Packet: " << response_string; 197 if (result != expected_result) 198 return make_error<StringError>( 199 formatv("Error sending message `{0}`: {1}", message, result).str(), 200 inconvertibleErrorCode()); 201 202 return Error::success(); 203 } 204 205 unsigned int TestClient::GetPcRegisterId() { 206 assert(m_pc_register != LLDB_INVALID_REGNUM); 207 return m_pc_register; 208 } 209 210 Error TestClient::qProcessInfo() { 211 m_process_info = None; 212 auto InfoOr = SendMessage<ProcessInfo>("qProcessInfo"); 213 if (!InfoOr) 214 return InfoOr.takeError(); 215 m_process_info = std::move(*InfoOr); 216 return Error::success(); 217 } 218 219 Error TestClient::qRegisterInfos() { 220 for (unsigned int Reg = 0;; ++Reg) { 221 std::string Message = formatv("qRegisterInfo{0:x-}", Reg).str(); 222 Expected<RegisterInfo> InfoOr = SendMessage<RegisterInfoParser>(Message); 223 if (!InfoOr) { 224 consumeError(InfoOr.takeError()); 225 break; 226 } 227 m_register_infos.emplace_back(std::move(*InfoOr)); 228 if (m_register_infos[Reg].kinds[eRegisterKindGeneric] == 229 LLDB_REGNUM_GENERIC_PC) 230 m_pc_register = Reg; 231 } 232 if (m_pc_register == LLDB_INVALID_REGNUM) 233 return make_parsing_error("qRegisterInfo: generic"); 234 return Error::success(); 235 } 236 237 Error TestClient::queryProcess() { 238 if (Error E = qProcessInfo()) 239 return E; 240 if (Error E = qRegisterInfos()) 241 return E; 242 return Error::success(); 243 } 244 245 Error TestClient::Continue(StringRef message) { 246 assert(m_process_info.hasValue()); 247 248 auto StopReplyOr = SendMessage<StopReply>( 249 message, m_process_info->GetEndian(), m_register_infos); 250 if (!StopReplyOr) 251 return StopReplyOr.takeError(); 252 253 m_stop_reply = std::move(*StopReplyOr); 254 if (!isa<StopReplyStop>(m_stop_reply)) { 255 StringExtractorGDBRemote R; 256 PacketResult result = ReadPacket(R, GetPacketTimeout(), false); 257 if (result != PacketResult::ErrorDisconnected) { 258 return make_error<StringError>( 259 formatv("Expected connection close after sending {0}. Got {1}/{2} " 260 "instead.", 261 message, result, R.GetStringRef()) 262 .str(), 263 inconvertibleErrorCode()); 264 } 265 } 266 return Error::success(); 267 } 268