1 //===-- GDBRemoteCommunicationServerPlatform.cpp --------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "GDBRemoteCommunicationServerPlatform.h" 10 11 #include <cerrno> 12 13 #include <chrono> 14 #include <csignal> 15 #include <cstring> 16 #include <mutex> 17 #include <optional> 18 #include <sstream> 19 #include <thread> 20 21 #include "llvm/Support/FileSystem.h" 22 #include "llvm/Support/JSON.h" 23 #include "llvm/Support/Threading.h" 24 25 #include "lldb/Host/Config.h" 26 #include "lldb/Host/ConnectionFileDescriptor.h" 27 #include "lldb/Host/FileAction.h" 28 #include "lldb/Host/Host.h" 29 #include "lldb/Host/HostInfo.h" 30 #include "lldb/Interpreter/CommandCompletions.h" 31 #include "lldb/Target/Platform.h" 32 #include "lldb/Target/UnixSignals.h" 33 #include "lldb/Utility/GDBRemote.h" 34 #include "lldb/Utility/LLDBLog.h" 35 #include "lldb/Utility/Log.h" 36 #include "lldb/Utility/StreamString.h" 37 #include "lldb/Utility/StructuredData.h" 38 #include "lldb/Utility/TildeExpressionResolver.h" 39 #include "lldb/Utility/UriParser.h" 40 41 #include "lldb/Utility/StringExtractorGDBRemote.h" 42 43 using namespace lldb; 44 using namespace lldb_private::process_gdb_remote; 45 using namespace lldb_private; 46 47 GDBRemoteCommunicationServerPlatform::PortMap::PortMap(uint16_t min_port, 48 uint16_t max_port) { 49 for (; min_port < max_port; ++min_port) 50 m_port_map[min_port] = LLDB_INVALID_PROCESS_ID; 51 } 52 53 void GDBRemoteCommunicationServerPlatform::PortMap::AllowPort(uint16_t port) { 54 // Do not modify existing mappings 55 m_port_map.insert({port, LLDB_INVALID_PROCESS_ID}); 56 } 57 58 llvm::Expected<uint16_t> 59 GDBRemoteCommunicationServerPlatform::PortMap::GetNextAvailablePort() { 60 if (m_port_map.empty()) 61 return 0; // Bind to port zero and get a port, we didn't have any 62 // limitations 63 64 for (auto &pair : m_port_map) { 65 if (pair.second == LLDB_INVALID_PROCESS_ID) { 66 pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID; 67 return pair.first; 68 } 69 } 70 return llvm::createStringError(llvm::inconvertibleErrorCode(), 71 "No free port found in port map"); 72 } 73 74 bool GDBRemoteCommunicationServerPlatform::PortMap::AssociatePortWithProcess( 75 uint16_t port, lldb::pid_t pid) { 76 auto pos = m_port_map.find(port); 77 if (pos != m_port_map.end()) { 78 pos->second = pid; 79 return true; 80 } 81 return false; 82 } 83 84 bool GDBRemoteCommunicationServerPlatform::PortMap::FreePort(uint16_t port) { 85 std::map<uint16_t, lldb::pid_t>::iterator pos = m_port_map.find(port); 86 if (pos != m_port_map.end()) { 87 pos->second = LLDB_INVALID_PROCESS_ID; 88 return true; 89 } 90 return false; 91 } 92 93 bool GDBRemoteCommunicationServerPlatform::PortMap::FreePortForProcess( 94 lldb::pid_t pid) { 95 if (!m_port_map.empty()) { 96 for (auto &pair : m_port_map) { 97 if (pair.second == pid) { 98 pair.second = LLDB_INVALID_PROCESS_ID; 99 return true; 100 } 101 } 102 } 103 return false; 104 } 105 106 bool GDBRemoteCommunicationServerPlatform::PortMap::empty() const { 107 return m_port_map.empty(); 108 } 109 110 // GDBRemoteCommunicationServerPlatform constructor 111 GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform( 112 const Socket::SocketProtocol socket_protocol, const char *socket_scheme) 113 : GDBRemoteCommunicationServerCommon(), 114 m_socket_protocol(socket_protocol), m_socket_scheme(socket_scheme), 115 m_spawned_pids_mutex(), m_port_map(), m_port_offset(0) { 116 m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID; 117 m_pending_gdb_server.port = 0; 118 119 RegisterMemberFunctionHandler( 120 StringExtractorGDBRemote::eServerPacketType_qC, 121 &GDBRemoteCommunicationServerPlatform::Handle_qC); 122 RegisterMemberFunctionHandler( 123 StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir, 124 &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir); 125 RegisterMemberFunctionHandler( 126 StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer, 127 &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer); 128 RegisterMemberFunctionHandler( 129 StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer, 130 &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer); 131 RegisterMemberFunctionHandler( 132 StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess, 133 &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess); 134 RegisterMemberFunctionHandler( 135 StringExtractorGDBRemote::eServerPacketType_qProcessInfo, 136 &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo); 137 RegisterMemberFunctionHandler( 138 StringExtractorGDBRemote::eServerPacketType_qPathComplete, 139 &GDBRemoteCommunicationServerPlatform::Handle_qPathComplete); 140 RegisterMemberFunctionHandler( 141 StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir, 142 &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir); 143 RegisterMemberFunctionHandler( 144 StringExtractorGDBRemote::eServerPacketType_jSignalsInfo, 145 &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo); 146 147 RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt, 148 [](StringExtractorGDBRemote packet, Status &error, 149 bool &interrupt, bool &quit) { 150 error.SetErrorString("interrupt received"); 151 interrupt = true; 152 return PacketResult::Success; 153 }); 154 } 155 156 // Destructor 157 GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() = 158 default; 159 160 Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer( 161 const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid, 162 std::optional<uint16_t> &port, std::string &socket_name) { 163 if (!port) { 164 llvm::Expected<uint16_t> available_port = m_port_map.GetNextAvailablePort(); 165 if (available_port) 166 port = *available_port; 167 else 168 return Status(available_port.takeError()); 169 } 170 171 // Spawn a new thread to accept the port that gets bound after binding to 172 // port 0 (zero). 173 174 // ignore the hostname send from the remote end, just use the ip address that 175 // we're currently communicating with as the hostname 176 177 // Spawn a debugserver and try to get the port it listens to. 178 ProcessLaunchInfo debugserver_launch_info; 179 if (hostname.empty()) 180 hostname = "127.0.0.1"; 181 182 Log *log = GetLog(LLDBLog::Platform); 183 LLDB_LOGF(log, "Launching debugserver with: %s:%u...", hostname.c_str(), 184 *port); 185 186 // Do not run in a new session so that it can not linger after the platform 187 // closes. 188 debugserver_launch_info.SetLaunchInSeparateProcessGroup(false); 189 debugserver_launch_info.SetMonitorProcessCallback( 190 std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, 191 this, std::placeholders::_1)); 192 193 std::ostringstream url; 194 // debugserver does not accept the URL scheme prefix. 195 #if !defined(__APPLE__) 196 url << m_socket_scheme << "://"; 197 #endif 198 uint16_t *port_ptr = &*port; 199 if (m_socket_protocol == Socket::ProtocolTcp) { 200 std::string platform_uri = GetConnection()->GetURI(); 201 std::optional<URI> parsed_uri = URI::Parse(platform_uri); 202 url << '[' << parsed_uri->hostname.str() << "]:" << *port; 203 } else { 204 socket_name = GetDomainSocketPath("gdbserver").GetPath(); 205 url << socket_name; 206 port_ptr = nullptr; 207 } 208 209 Status error = StartDebugserverProcess( 210 url.str().c_str(), nullptr, debugserver_launch_info, port_ptr, &args, -1); 211 212 pid = debugserver_launch_info.GetProcessID(); 213 if (pid != LLDB_INVALID_PROCESS_ID) { 214 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); 215 m_spawned_pids.insert(pid); 216 if (*port > 0) 217 m_port_map.AssociatePortWithProcess(*port, pid); 218 } else { 219 if (*port > 0) 220 m_port_map.FreePort(*port); 221 } 222 return error; 223 } 224 225 GDBRemoteCommunication::PacketResult 226 GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer( 227 StringExtractorGDBRemote &packet) { 228 // Spawn a local debugserver as a platform so we can then attach or launch a 229 // process... 230 231 Log *log = GetLog(LLDBLog::Platform); 232 LLDB_LOGF(log, "GDBRemoteCommunicationServerPlatform::%s() called", 233 __FUNCTION__); 234 235 ConnectionFileDescriptor file_conn; 236 std::string hostname; 237 packet.SetFilePos(::strlen("qLaunchGDBServer;")); 238 llvm::StringRef name; 239 llvm::StringRef value; 240 std::optional<uint16_t> port; 241 while (packet.GetNameColonValue(name, value)) { 242 if (name.equals("host")) 243 hostname = std::string(value); 244 else if (name.equals("port")) { 245 // Make the Optional valid so we can use its value 246 port = 0; 247 value.getAsInteger(0, *port); 248 } 249 } 250 251 lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; 252 std::string socket_name; 253 Status error = 254 LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name); 255 if (error.Fail()) { 256 LLDB_LOGF(log, 257 "GDBRemoteCommunicationServerPlatform::%s() debugserver " 258 "launch failed: %s", 259 __FUNCTION__, error.AsCString()); 260 return SendErrorResponse(9); 261 } 262 263 LLDB_LOGF(log, 264 "GDBRemoteCommunicationServerPlatform::%s() debugserver " 265 "launched successfully as pid %" PRIu64, 266 __FUNCTION__, debugserver_pid); 267 268 StreamGDBRemote response; 269 assert(port); 270 response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, 271 *port + m_port_offset); 272 if (!socket_name.empty()) { 273 response.PutCString("socket_name:"); 274 response.PutStringAsRawHex8(socket_name); 275 response.PutChar(';'); 276 } 277 278 PacketResult packet_result = SendPacketNoLock(response.GetString()); 279 if (packet_result != PacketResult::Success) { 280 if (debugserver_pid != LLDB_INVALID_PROCESS_ID) 281 Host::Kill(debugserver_pid, SIGINT); 282 } 283 return packet_result; 284 } 285 286 GDBRemoteCommunication::PacketResult 287 GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer( 288 StringExtractorGDBRemote &packet) { 289 namespace json = llvm::json; 290 291 if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID) 292 return SendErrorResponse(4); 293 294 json::Object server{{"port", m_pending_gdb_server.port}}; 295 296 if (!m_pending_gdb_server.socket_name.empty()) 297 server.try_emplace("socket_name", m_pending_gdb_server.socket_name); 298 299 json::Array server_list; 300 server_list.push_back(std::move(server)); 301 302 StreamGDBRemote response; 303 response.AsRawOstream() << std::move(server_list); 304 305 StreamGDBRemote escaped_response; 306 escaped_response.PutEscapedBytes(response.GetString().data(), 307 response.GetSize()); 308 return SendPacketNoLock(escaped_response.GetString()); 309 } 310 311 GDBRemoteCommunication::PacketResult 312 GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess( 313 StringExtractorGDBRemote &packet) { 314 packet.SetFilePos(::strlen("qKillSpawnedProcess:")); 315 316 lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID); 317 318 // verify that we know anything about this pid. Scope for locker 319 { 320 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); 321 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) { 322 // not a pid we know about 323 return SendErrorResponse(10); 324 } 325 } 326 327 // go ahead and attempt to kill the spawned process 328 if (KillSpawnedProcess(pid)) 329 return SendOKResponse(); 330 else 331 return SendErrorResponse(11); 332 } 333 334 bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) { 335 // make sure we know about this process 336 { 337 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); 338 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) 339 return false; 340 } 341 342 // first try a SIGTERM (standard kill) 343 Host::Kill(pid, SIGTERM); 344 345 // check if that worked 346 for (size_t i = 0; i < 10; ++i) { 347 { 348 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); 349 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) { 350 // it is now killed 351 return true; 352 } 353 } 354 std::this_thread::sleep_for(std::chrono::milliseconds(10)); 355 } 356 357 { 358 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); 359 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) 360 return true; 361 } 362 363 // the launched process still lives. Now try killing it again, this time 364 // with an unblockable signal. 365 Host::Kill(pid, SIGKILL); 366 367 for (size_t i = 0; i < 10; ++i) { 368 { 369 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); 370 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) { 371 // it is now killed 372 return true; 373 } 374 } 375 std::this_thread::sleep_for(std::chrono::milliseconds(10)); 376 } 377 378 // check one more time after the final sleep 379 { 380 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); 381 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) 382 return true; 383 } 384 385 // no luck - the process still lives 386 return false; 387 } 388 389 GDBRemoteCommunication::PacketResult 390 GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo( 391 StringExtractorGDBRemote &packet) { 392 lldb::pid_t pid = m_process_launch_info.GetProcessID(); 393 m_process_launch_info.Clear(); 394 395 if (pid == LLDB_INVALID_PROCESS_ID) 396 return SendErrorResponse(1); 397 398 ProcessInstanceInfo proc_info; 399 if (!Host::GetProcessInfo(pid, proc_info)) 400 return SendErrorResponse(1); 401 402 StreamString response; 403 CreateProcessInfoResponse_DebugServerStyle(proc_info, response); 404 return SendPacketNoLock(response.GetString()); 405 } 406 407 GDBRemoteCommunication::PacketResult 408 GDBRemoteCommunicationServerPlatform::Handle_qPathComplete( 409 StringExtractorGDBRemote &packet) { 410 packet.SetFilePos(::strlen("qPathComplete:")); 411 const bool only_dir = (packet.GetHexMaxU32(false, 0) == 1); 412 if (packet.GetChar() != ',') 413 return SendErrorResponse(85); 414 std::string path; 415 packet.GetHexByteString(path); 416 417 StringList matches; 418 StandardTildeExpressionResolver resolver; 419 if (only_dir) 420 CommandCompletions::DiskDirectories(path, matches, resolver); 421 else 422 CommandCompletions::DiskFiles(path, matches, resolver); 423 424 StreamString response; 425 response.PutChar('M'); 426 llvm::StringRef separator; 427 std::sort(matches.begin(), matches.end()); 428 for (const auto &match : matches) { 429 response << separator; 430 separator = ","; 431 // encode result strings into hex bytes to avoid unexpected error caused by 432 // special characters like '$'. 433 response.PutStringAsRawHex8(match.c_str()); 434 } 435 436 return SendPacketNoLock(response.GetString()); 437 } 438 439 GDBRemoteCommunication::PacketResult 440 GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir( 441 StringExtractorGDBRemote &packet) { 442 443 llvm::SmallString<64> cwd; 444 if (std::error_code ec = llvm::sys::fs::current_path(cwd)) 445 return SendErrorResponse(ec.value()); 446 447 StreamString response; 448 response.PutBytesAsRawHex8(cwd.data(), cwd.size()); 449 return SendPacketNoLock(response.GetString()); 450 } 451 452 GDBRemoteCommunication::PacketResult 453 GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir( 454 StringExtractorGDBRemote &packet) { 455 packet.SetFilePos(::strlen("QSetWorkingDir:")); 456 std::string path; 457 packet.GetHexByteString(path); 458 459 if (std::error_code ec = llvm::sys::fs::set_current_path(path)) 460 return SendErrorResponse(ec.value()); 461 return SendOKResponse(); 462 } 463 464 GDBRemoteCommunication::PacketResult 465 GDBRemoteCommunicationServerPlatform::Handle_qC( 466 StringExtractorGDBRemote &packet) { 467 // NOTE: lldb should now be using qProcessInfo for process IDs. This path 468 // here 469 // should not be used. It is reporting process id instead of thread id. The 470 // correct answer doesn't seem to make much sense for lldb-platform. 471 // CONSIDER: flip to "unsupported". 472 lldb::pid_t pid = m_process_launch_info.GetProcessID(); 473 474 StreamString response; 475 response.Printf("QC%" PRIx64, pid); 476 477 // If we launch a process and this GDB server is acting as a platform, then 478 // we need to clear the process launch state so we can start launching 479 // another process. In order to launch a process a bunch or packets need to 480 // be sent: environment packets, working directory, disable ASLR, and many 481 // more settings. When we launch a process we then need to know when to clear 482 // this information. Currently we are selecting the 'qC' packet as that 483 // packet which seems to make the most sense. 484 if (pid != LLDB_INVALID_PROCESS_ID) { 485 m_process_launch_info.Clear(); 486 } 487 488 return SendPacketNoLock(response.GetString()); 489 } 490 491 GDBRemoteCommunication::PacketResult 492 GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo( 493 StringExtractorGDBRemote &packet) { 494 StructuredData::Array signal_array; 495 496 lldb::UnixSignalsSP signals = UnixSignals::CreateForHost(); 497 for (auto signo = signals->GetFirstSignalNumber(); 498 signo != LLDB_INVALID_SIGNAL_NUMBER; 499 signo = signals->GetNextSignalNumber(signo)) { 500 auto dictionary = std::make_shared<StructuredData::Dictionary>(); 501 502 dictionary->AddIntegerItem("signo", signo); 503 dictionary->AddStringItem("name", signals->GetSignalAsCString(signo)); 504 505 bool suppress, stop, notify; 506 signals->GetSignalInfo(signo, suppress, stop, notify); 507 dictionary->AddBooleanItem("suppress", suppress); 508 dictionary->AddBooleanItem("stop", stop); 509 dictionary->AddBooleanItem("notify", notify); 510 511 signal_array.Push(dictionary); 512 } 513 514 StreamString response; 515 signal_array.Dump(response); 516 return SendPacketNoLock(response.GetString()); 517 } 518 519 void GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped( 520 lldb::pid_t pid) { 521 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); 522 m_port_map.FreePortForProcess(pid); 523 m_spawned_pids.erase(pid); 524 } 525 526 Status GDBRemoteCommunicationServerPlatform::LaunchProcess() { 527 if (!m_process_launch_info.GetArguments().GetArgumentCount()) 528 return Status("%s: no process command line specified to launch", 529 __FUNCTION__); 530 531 // specify the process monitor if not already set. This should generally be 532 // what happens since we need to reap started processes. 533 if (!m_process_launch_info.GetMonitorProcessCallback()) 534 m_process_launch_info.SetMonitorProcessCallback(std::bind( 535 &GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this, 536 std::placeholders::_1)); 537 538 Status error = Host::LaunchProcess(m_process_launch_info); 539 if (!error.Success()) { 540 fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__, 541 m_process_launch_info.GetArguments().GetArgumentAtIndex(0)); 542 return error; 543 } 544 545 printf("Launched '%s' as process %" PRIu64 "...\n", 546 m_process_launch_info.GetArguments().GetArgumentAtIndex(0), 547 m_process_launch_info.GetProcessID()); 548 549 // add to list of spawned processes. On an lldb-gdbserver, we would expect 550 // there to be only one. 551 const auto pid = m_process_launch_info.GetProcessID(); 552 if (pid != LLDB_INVALID_PROCESS_ID) { 553 // add to spawned pids 554 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); 555 m_spawned_pids.insert(pid); 556 } 557 558 return error; 559 } 560 561 void GDBRemoteCommunicationServerPlatform::SetPortMap(PortMap &&port_map) { 562 m_port_map = std::move(port_map); 563 } 564 565 const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() { 566 static FileSpec g_domainsocket_dir; 567 static llvm::once_flag g_once_flag; 568 569 llvm::call_once(g_once_flag, []() { 570 const char *domainsocket_dir_env = 571 ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR"); 572 if (domainsocket_dir_env != nullptr) 573 g_domainsocket_dir = FileSpec(domainsocket_dir_env); 574 else 575 g_domainsocket_dir = HostInfo::GetProcessTempDir(); 576 }); 577 578 return g_domainsocket_dir; 579 } 580 581 FileSpec 582 GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char *prefix) { 583 llvm::SmallString<128> socket_path; 584 llvm::SmallString<128> socket_name( 585 (llvm::StringRef(prefix) + ".%%%%%%").str()); 586 587 FileSpec socket_path_spec(GetDomainSocketDir()); 588 socket_path_spec.AppendPathComponent(socket_name.c_str()); 589 590 llvm::sys::fs::createUniqueFile(socket_path_spec.GetPath().c_str(), 591 socket_path); 592 return FileSpec(socket_path.c_str()); 593 } 594 595 void GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset) { 596 m_port_offset = port_offset; 597 } 598 599 void GDBRemoteCommunicationServerPlatform::SetPendingGdbServer( 600 lldb::pid_t pid, uint16_t port, const std::string &socket_name) { 601 m_pending_gdb_server.pid = pid; 602 m_pending_gdb_server.port = port; 603 m_pending_gdb_server.socket_name = socket_name; 604 } 605