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