1 //===-- GDBRemoteCommunicationServerPlatform.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 "GDBRemoteCommunicationServerPlatform.h" 11 12 #include <errno.h> 13 14 // C Includes 15 // C++ Includes 16 #include <cstring> 17 #include <chrono> 18 19 // Other libraries and framework includes 20 #include "lldb/Core/Log.h" 21 #include "lldb/Core/StreamString.h" 22 #include "lldb/Core/StructuredData.h" 23 #include "lldb/Host/Config.h" 24 #include "lldb/Host/ConnectionFileDescriptor.h" 25 #include "lldb/Host/Host.h" 26 #include "lldb/Host/StringConvert.h" 27 #include "lldb/Target/FileAction.h" 28 #include "lldb/Target/Platform.h" 29 #include "lldb/Target/Process.h" 30 #include "lldb/Target/UnixSignals.h" 31 32 // Project includes 33 #include "Utility/StringExtractorGDBRemote.h" 34 #include "Utility/UriParser.h" 35 36 using namespace lldb; 37 using namespace lldb_private; 38 using namespace lldb_private::process_gdb_remote; 39 40 //---------------------------------------------------------------------- 41 // GDBRemoteCommunicationServerPlatform constructor 42 //---------------------------------------------------------------------- 43 GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform() : 44 GDBRemoteCommunicationServerCommon ("gdb-remote.server", "gdb-remote.server.rx_packet"), 45 m_platform_sp (Platform::GetHostPlatform ()), 46 m_port_map (), 47 m_port_offset(0) 48 { 49 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC, 50 &GDBRemoteCommunicationServerPlatform::Handle_qC); 51 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir, 52 &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir); 53 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer, 54 &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer); 55 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qProcessInfo, 56 &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo); 57 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir, 58 &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir); 59 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_jSignalsInfo, 60 &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo); 61 62 RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt, 63 [this](StringExtractorGDBRemote packet, 64 Error &error, 65 bool &interrupt, 66 bool &quit) 67 { 68 error.SetErrorString("interrupt received"); 69 interrupt = true; 70 return PacketResult::Success; 71 }); 72 } 73 74 //---------------------------------------------------------------------- 75 // Destructor 76 //---------------------------------------------------------------------- 77 GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() 78 { 79 } 80 81 GDBRemoteCommunication::PacketResult 82 GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet) 83 { 84 #ifdef _WIN32 85 return SendErrorResponse(9); 86 #else 87 // Spawn a local debugserver as a platform so we can then attach or launch 88 // a process... 89 90 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 91 if (log) 92 log->Printf ("GDBRemoteCommunicationServerPlatform::%s() called", __FUNCTION__); 93 94 // Sleep and wait a bit for debugserver to start to listen... 95 ConnectionFileDescriptor file_conn; 96 std::string hostname; 97 // TODO: /tmp/ should not be hardcoded. User might want to override /tmp 98 // with the TMPDIR environment variable 99 packet.SetFilePos(::strlen ("qLaunchGDBServer;")); 100 std::string name; 101 std::string value; 102 uint16_t port = UINT16_MAX; 103 while (packet.GetNameColonValue(name, value)) 104 { 105 if (name.compare ("host") == 0) 106 hostname.swap(value); 107 else if (name.compare ("port") == 0) 108 port = StringConvert::ToUInt32(value.c_str(), 0, 0); 109 } 110 if (port == UINT16_MAX) 111 port = GetNextAvailablePort(); 112 113 // Spawn a new thread to accept the port that gets bound after 114 // binding to port 0 (zero). 115 116 // ignore the hostname send from the remote end, just use the ip address 117 // that we're currently communicating with as the hostname 118 119 // Spawn a debugserver and try to get the port it listens to. 120 ProcessLaunchInfo debugserver_launch_info; 121 if (hostname.empty()) 122 hostname = "127.0.0.1"; 123 if (log) 124 log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port); 125 126 // Do not run in a new session so that it can not linger after the 127 // platform closes. 128 debugserver_launch_info.SetLaunchInSeparateProcessGroup(false); 129 debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false); 130 131 std::string platform_scheme; 132 std::string platform_ip; 133 int platform_port; 134 std::string platform_path; 135 bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path); 136 UNUSED_IF_ASSERT_DISABLED(ok); 137 assert(ok); 138 Error error = StartDebugserverProcess ( 139 platform_ip.c_str(), 140 port, 141 debugserver_launch_info, 142 port); 143 144 lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID(); 145 146 147 if (debugserver_pid != LLDB_INVALID_PROCESS_ID) 148 { 149 Mutex::Locker locker (m_spawned_pids_mutex); 150 m_spawned_pids.insert(debugserver_pid); 151 if (port > 0) 152 AssociatePortWithProcess(port, debugserver_pid); 153 } 154 else 155 { 156 if (port > 0) 157 FreePort (port); 158 } 159 160 if (error.Success()) 161 { 162 if (log) 163 log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid); 164 165 char response[256]; 166 const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset); 167 assert (response_len < (int)sizeof(response)); 168 PacketResult packet_result = SendPacketNoLock (response, response_len); 169 170 if (packet_result != PacketResult::Success) 171 { 172 if (debugserver_pid != LLDB_INVALID_PROCESS_ID) 173 ::kill (debugserver_pid, SIGINT); 174 } 175 return packet_result; 176 } 177 else 178 { 179 if (log) 180 log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ()); 181 } 182 return SendErrorResponse (9); 183 #endif 184 } 185 186 GDBRemoteCommunication::PacketResult 187 GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo (StringExtractorGDBRemote &packet) 188 { 189 lldb::pid_t pid = m_process_launch_info.GetProcessID (); 190 m_process_launch_info.Clear (); 191 192 if (pid == LLDB_INVALID_PROCESS_ID) 193 return SendErrorResponse (1); 194 195 ProcessInstanceInfo proc_info; 196 if (!Host::GetProcessInfo (pid, proc_info)) 197 return SendErrorResponse (1); 198 199 StreamString response; 200 CreateProcessInfoResponse_DebugServerStyle(proc_info, response); 201 return SendPacketNoLock (response.GetData (), response.GetSize ()); 202 } 203 204 GDBRemoteCommunication::PacketResult 205 GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet) 206 { 207 // If this packet is sent to a platform, then change the current working directory 208 209 char cwd[PATH_MAX]; 210 if (getcwd(cwd, sizeof(cwd)) == NULL) 211 return SendErrorResponse(errno); 212 213 StreamString response; 214 response.PutBytesAsRawHex8(cwd, strlen(cwd)); 215 return SendPacketNoLock(response.GetData(), response.GetSize()); 216 } 217 218 GDBRemoteCommunication::PacketResult 219 GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet) 220 { 221 packet.SetFilePos (::strlen ("QSetWorkingDir:")); 222 std::string path; 223 packet.GetHexByteString (path); 224 225 // If this packet is sent to a platform, then change the current working directory 226 if (::chdir(path.c_str()) != 0) 227 return SendErrorResponse (errno); 228 return SendOKResponse (); 229 } 230 231 GDBRemoteCommunication::PacketResult 232 GDBRemoteCommunicationServerPlatform::Handle_qC (StringExtractorGDBRemote &packet) 233 { 234 // NOTE: lldb should now be using qProcessInfo for process IDs. This path here 235 // should not be used. It is reporting process id instead of thread id. The 236 // correct answer doesn't seem to make much sense for lldb-platform. 237 // CONSIDER: flip to "unsupported". 238 lldb::pid_t pid = m_process_launch_info.GetProcessID(); 239 240 StreamString response; 241 response.Printf("QC%" PRIx64, pid); 242 243 // If we launch a process and this GDB server is acting as a platform, 244 // then we need to clear the process launch state so we can start 245 // launching another process. In order to launch a process a bunch or 246 // packets need to be sent: environment packets, working directory, 247 // disable ASLR, and many more settings. When we launch a process we 248 // then need to know when to clear this information. Currently we are 249 // selecting the 'qC' packet as that packet which seems to make the most 250 // sense. 251 if (pid != LLDB_INVALID_PROCESS_ID) 252 { 253 m_process_launch_info.Clear(); 254 } 255 256 return SendPacketNoLock (response.GetData(), response.GetSize()); 257 } 258 259 GDBRemoteCommunication::PacketResult 260 GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(StringExtractorGDBRemote &packet) 261 { 262 StructuredData::Array signal_array; 263 264 const auto &signals = Host::GetUnixSignals(); 265 for (auto signo = signals->GetFirstSignalNumber(); 266 signo != LLDB_INVALID_SIGNAL_NUMBER; 267 signo = signals->GetNextSignalNumber(signo)) 268 { 269 auto dictionary = std::make_shared<StructuredData::Dictionary>(); 270 271 dictionary->AddIntegerItem("signo", signo); 272 dictionary->AddStringItem("name", signals->GetSignalAsCString(signo)); 273 274 bool suppress, stop, notify; 275 signals->GetSignalInfo(signo, suppress, stop, notify); 276 dictionary->AddBooleanItem("suppress", suppress); 277 dictionary->AddBooleanItem("stop", stop); 278 dictionary->AddBooleanItem("notify", notify); 279 280 signal_array.Push(dictionary); 281 } 282 283 StreamString response; 284 signal_array.Dump(response); 285 return SendPacketNoLock(response.GetData(), response.GetSize()); 286 } 287 288 bool 289 GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped (lldb::pid_t pid) 290 { 291 Mutex::Locker locker (m_spawned_pids_mutex); 292 FreePortForProcess(pid); 293 return m_spawned_pids.erase(pid) > 0; 294 } 295 296 bool 297 GDBRemoteCommunicationServerPlatform::ReapDebugserverProcess (void *callback_baton, 298 lldb::pid_t pid, 299 bool exited, 300 int signal, // Zero for no signal 301 int status) // Exit value of process if signal is zero 302 { 303 GDBRemoteCommunicationServerPlatform *server = (GDBRemoteCommunicationServerPlatform *)callback_baton; 304 server->DebugserverProcessReaped (pid); 305 return true; 306 } 307 308 Error 309 GDBRemoteCommunicationServerPlatform::LaunchProcess () 310 { 311 if (!m_process_launch_info.GetArguments ().GetArgumentCount ()) 312 return Error ("%s: no process command line specified to launch", __FUNCTION__); 313 314 // specify the process monitor if not already set. This should 315 // generally be what happens since we need to reap started 316 // processes. 317 if (!m_process_launch_info.GetMonitorProcessCallback ()) 318 m_process_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false); 319 320 Error error = m_platform_sp->LaunchProcess (m_process_launch_info); 321 if (!error.Success ()) 322 { 323 fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0)); 324 return error; 325 } 326 327 printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID()); 328 329 // add to list of spawned processes. On an lldb-gdbserver, we 330 // would expect there to be only one. 331 const auto pid = m_process_launch_info.GetProcessID(); 332 if (pid != LLDB_INVALID_PROCESS_ID) 333 { 334 // add to spawned pids 335 Mutex::Locker locker (m_spawned_pids_mutex); 336 m_spawned_pids.insert(pid); 337 } 338 339 return error; 340 } 341 342 void 343 GDBRemoteCommunicationServerPlatform::SetPortMap (PortMap &&port_map) 344 { 345 m_port_map = port_map; 346 } 347 348 uint16_t 349 GDBRemoteCommunicationServerPlatform::GetNextAvailablePort () 350 { 351 if (m_port_map.empty()) 352 return 0; // Bind to port zero and get a port, we didn't have any limitations 353 354 for (auto &pair : m_port_map) 355 { 356 if (pair.second == LLDB_INVALID_PROCESS_ID) 357 { 358 pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID; 359 return pair.first; 360 } 361 } 362 return UINT16_MAX; 363 } 364 365 bool 366 GDBRemoteCommunicationServerPlatform::AssociatePortWithProcess (uint16_t port, lldb::pid_t pid) 367 { 368 PortMap::iterator pos = m_port_map.find(port); 369 if (pos != m_port_map.end()) 370 { 371 pos->second = pid; 372 return true; 373 } 374 return false; 375 } 376 377 bool 378 GDBRemoteCommunicationServerPlatform::FreePort (uint16_t port) 379 { 380 PortMap::iterator pos = m_port_map.find(port); 381 if (pos != m_port_map.end()) 382 { 383 pos->second = LLDB_INVALID_PROCESS_ID; 384 return true; 385 } 386 return false; 387 } 388 389 bool 390 GDBRemoteCommunicationServerPlatform::FreePortForProcess (lldb::pid_t pid) 391 { 392 if (!m_port_map.empty()) 393 { 394 for (auto &pair : m_port_map) 395 { 396 if (pair.second == pid) 397 { 398 pair.second = LLDB_INVALID_PROCESS_ID; 399 return true; 400 } 401 } 402 } 403 return false; 404 } 405 406 void 407 GDBRemoteCommunicationServerPlatform::SetPortOffset (uint16_t port_offset) 408 { 409 m_port_offset = port_offset; 410 } 411