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