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/Core/ArchSpec.h" 12 #include "lldb/Host/HostInfo.h" 13 #include "lldb/Host/common/TCPSocket.h" 14 #include "lldb/Host/posix/ConnectionFileDescriptorPosix.h" 15 #include "lldb/Interpreter/Args.h" 16 #include "lldb/Target/ProcessLaunchInfo.h" 17 #include "llvm/ADT/StringExtras.h" 18 #include "gtest/gtest.h" 19 #include <cstdlib> 20 #include <future> 21 #include <sstream> 22 #include <string> 23 24 using namespace lldb; 25 using namespace lldb_private; 26 using namespace llvm; 27 28 namespace llgs_tests { 29 void TestClient::Initialize() { HostInfo::Initialize(); } 30 31 TestClient::TestClient(const std::string &test_name, 32 const std::string &test_case_name) 33 : m_test_name(test_name), m_test_case_name(test_case_name), 34 m_pc_register(UINT_MAX) {} 35 36 TestClient::~TestClient() {} 37 38 bool TestClient::StartDebugger() { 39 const ArchSpec &arch_spec = HostInfo::GetArchitecture(); 40 Args args; 41 args.AppendArgument(LLDB_SERVER); 42 args.AppendArgument("gdbserver"); 43 args.AppendArgument("--log-channels=gdb-remote packets"); 44 args.AppendArgument("--reverse-connect"); 45 std::string log_file_name = GenerateLogFileName(arch_spec); 46 if (log_file_name.size()) { 47 args.AppendArgument("--log-file=" + log_file_name); 48 } 49 50 Status error; 51 TCPSocket listen_socket(true, false); 52 error = listen_socket.Listen("127.0.0.1:0", 5); 53 if (error.Fail()) { 54 GTEST_LOG_(ERROR) << "Unable to open listen socket."; 55 return false; 56 } 57 58 char connect_remote_address[64]; 59 snprintf(connect_remote_address, sizeof(connect_remote_address), 60 "localhost:%u", listen_socket.GetLocalPortNumber()); 61 62 args.AppendArgument(connect_remote_address); 63 64 m_server_process_info.SetArchitecture(arch_spec); 65 m_server_process_info.SetArguments(args, true); 66 Status status = Host::LaunchProcess(m_server_process_info); 67 if (status.Fail()) { 68 GTEST_LOG_(ERROR) 69 << formatv("Failure to launch lldb server: {0}.", status).str(); 70 return false; 71 } 72 73 char connect_remote_uri[64]; 74 snprintf(connect_remote_uri, sizeof(connect_remote_uri), "connect://%s", 75 connect_remote_address); 76 Socket *accept_socket; 77 listen_socket.Accept(accept_socket); 78 SetConnection(new ConnectionFileDescriptor(accept_socket)); 79 80 SendAck(); // Send this as a handshake. 81 return true; 82 } 83 84 bool TestClient::StopDebugger() { 85 std::string response; 86 return SendMessage("k", response, PacketResult::ErrorDisconnected); 87 } 88 89 bool TestClient::SetInferior(llvm::ArrayRef<std::string> inferior_args) { 90 std::stringstream command; 91 command << "A"; 92 for (size_t i = 0; i < inferior_args.size(); i++) { 93 if (i > 0) 94 command << ','; 95 std::string hex_encoded = toHex(inferior_args[i]); 96 command << hex_encoded.size() << ',' << i << ',' << hex_encoded; 97 } 98 99 if (!SendMessage(command.str())) 100 return false; 101 if (!SendMessage("qLaunchSuccess")) 102 return false; 103 std::string response; 104 if (!SendMessage("qProcessInfo", response)) 105 return false; 106 auto create_or_error = ProcessInfo::Create(response); 107 if (auto create_error = create_or_error.takeError()) { 108 GTEST_LOG_(ERROR) << toString(std::move(create_error)); 109 return false; 110 } 111 112 m_process_info = *create_or_error; 113 return true; 114 } 115 116 bool TestClient::ListThreadsInStopReply() { 117 return SendMessage("QListThreadsInStopReply"); 118 } 119 120 bool TestClient::SetBreakpoint(unsigned long address) { 121 std::stringstream command; 122 command << "Z0," << std::hex << address << ",1"; 123 return SendMessage(command.str()); 124 } 125 126 bool TestClient::ContinueAll() { return Continue("vCont;c"); } 127 128 bool TestClient::ContinueThread(unsigned long thread_id) { 129 return Continue(formatv("vCont;c:{0:x-}", thread_id).str()); 130 } 131 132 const ProcessInfo &TestClient::GetProcessInfo() { return *m_process_info; } 133 134 Optional<JThreadsInfo> TestClient::GetJThreadsInfo() { 135 std::string response; 136 if (!SendMessage("jThreadsInfo", response)) 137 return llvm::None; 138 auto creation = JThreadsInfo::Create(response, m_process_info->GetEndian()); 139 if (auto create_error = creation.takeError()) { 140 GTEST_LOG_(ERROR) << toString(std::move(create_error)); 141 return llvm::None; 142 } 143 144 return std::move(*creation); 145 } 146 147 const StopReply &TestClient::GetLatestStopReply() { 148 return m_stop_reply.getValue(); 149 } 150 151 bool TestClient::SendMessage(StringRef message) { 152 std::string dummy_string; 153 return SendMessage(message, dummy_string); 154 } 155 156 bool TestClient::SendMessage(StringRef message, std::string &response_string) { 157 if (!SendMessage(message, response_string, PacketResult::Success)) 158 return false; 159 else if (response_string[0] == 'E') { 160 GTEST_LOG_(ERROR) << "Error " << response_string 161 << " while sending message: " << message.str(); 162 return false; 163 } 164 165 return true; 166 } 167 168 bool TestClient::SendMessage(StringRef message, std::string &response_string, 169 PacketResult expected_result) { 170 StringExtractorGDBRemote response; 171 GTEST_LOG_(INFO) << "Send Packet: " << message.str(); 172 PacketResult result = SendPacketAndWaitForResponse(message, response, false); 173 response.GetEscapedBinaryData(response_string); 174 GTEST_LOG_(INFO) << "Read Packet: " << response_string; 175 if (result != expected_result) { 176 GTEST_LOG_(ERROR) << FormatFailedResult(message, result); 177 return false; 178 } 179 180 return true; 181 } 182 183 unsigned int TestClient::GetPcRegisterId() { 184 if (m_pc_register != UINT_MAX) 185 return m_pc_register; 186 187 for (unsigned int register_id = 0;; register_id++) { 188 std::string message = formatv("qRegisterInfo{0:x-}", register_id).str(); 189 std::string response; 190 if (!SendMessage(message, response)) { 191 GTEST_LOG_(ERROR) << "Unable to query register ID for PC register."; 192 return UINT_MAX; 193 } 194 195 auto elements_or_error = SplitPairList("GetPcRegisterId", response); 196 if (auto split_error = elements_or_error.takeError()) { 197 GTEST_LOG_(ERROR) << "GetPcRegisterId: Error splitting response: " 198 << response; 199 return UINT_MAX; 200 } 201 202 auto elements = *elements_or_error; 203 if (elements["alt-name"] == "pc" || elements["generic"] == "pc") { 204 m_pc_register = register_id; 205 break; 206 } 207 } 208 209 return m_pc_register; 210 } 211 212 bool TestClient::Continue(StringRef message) { 213 if (!m_process_info.hasValue()) { 214 GTEST_LOG_(ERROR) << "Continue() called before m_process_info initialized."; 215 return false; 216 } 217 218 std::string response; 219 if (!SendMessage(message, response)) 220 return false; 221 auto creation = StopReply::Create(response, m_process_info->GetEndian()); 222 if (auto create_error = creation.takeError()) { 223 GTEST_LOG_(ERROR) << toString(std::move(create_error)); 224 return false; 225 } 226 227 m_stop_reply = std::move(*creation); 228 return true; 229 } 230 231 std::string TestClient::GenerateLogFileName(const ArchSpec &arch) const { 232 char *log_directory = getenv("LOG_FILE_DIRECTORY"); 233 if (!log_directory) 234 return ""; 235 236 if (!llvm::sys::fs::is_directory(log_directory)) { 237 GTEST_LOG_(WARNING) << "Cannot access log directory: " << log_directory; 238 return ""; 239 } 240 241 std::string log_file_name; 242 raw_string_ostream log_file(log_file_name); 243 log_file << log_directory << "/lldb-" << m_test_case_name << '-' 244 << m_test_name << '-' << arch.GetArchitectureName() << ".log"; 245 return log_file.str(); 246 } 247 248 std::string TestClient::FormatFailedResult(const std::string &message, 249 PacketResult result) { 250 std::string formatted_error; 251 raw_string_ostream error_stream(formatted_error); 252 error_stream << "Failure sending message: " << message << " Result: "; 253 254 switch (result) { 255 case PacketResult::ErrorSendFailed: 256 error_stream << "ErrorSendFailed"; 257 break; 258 case PacketResult::ErrorSendAck: 259 error_stream << "ErrorSendAck"; 260 break; 261 case PacketResult::ErrorReplyFailed: 262 error_stream << "ErrorReplyFailed"; 263 break; 264 case PacketResult::ErrorReplyTimeout: 265 error_stream << "ErrorReplyTimeout"; 266 break; 267 case PacketResult::ErrorReplyInvalid: 268 error_stream << "ErrorReplyInvalid"; 269 break; 270 case PacketResult::ErrorReplyAck: 271 error_stream << "ErrorReplyAck"; 272 break; 273 case PacketResult::ErrorDisconnected: 274 error_stream << "ErrorDisconnected"; 275 break; 276 case PacketResult::ErrorNoSequenceLock: 277 error_stream << "ErrorNoSequenceLock"; 278 break; 279 default: 280 error_stream << "Unknown Error"; 281 } 282 283 error_stream.str(); 284 return formatted_error; 285 } 286 } // namespace llgs_tests 287