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