GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer( StringExtractorGDBRemote &packet) { if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID) return SendErrorResponse(4); JSONObject::SP server_sp = std::make_shared<JSONObject>(); server_sp->SetObject("port", std::make_shared<JSONNumber>(m_pending_gdb_server.port)); if (!m_pending_gdb_server.socket_name.empty()) server_sp->SetObject( "socket_name", std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str())); JSONArray server_list; server_list.AppendObject(server_sp); StreamGDBRemote response; server_list.Write(response); StreamGDBRemote escaped_response; escaped_response.PutEscapedBytes(response.GetString().data(), response.GetSize()); return SendPacketNoLock(escaped_response.GetString()); }
TEST_F(GDBRemoteClientBaseTest, SendContinueDelegateStructuredDataReceipt) { // Build the plain-text version of the JSON data we will have the // server send. const std::string json_payload = "{ \"type\": \"MyFeatureType\", " " \"elements\": [ \"entry1\", \"entry2\" ] }"; const std::string json_packet = "JSON-async:" + json_payload; // Escape it properly for transit. StreamGDBRemote stream; stream.PutEscapedBytes(json_packet.c_str(), json_packet.length()); stream.Flush(); StringExtractorGDBRemote response; // Send async structured data packet, then stop. ASSERT_EQ(PacketResult::Success, server.SendPacket(stream.GetData())); ASSERT_EQ(PacketResult::Success, server.SendPacket("T01")); ASSERT_EQ(eStateStopped, SendCPacket(response)); ASSERT_EQ("T01", response.GetStringRef()); ASSERT_EQ(1ul, delegate.structured_data_packets.size()); // Verify the packet contents. It should have been unescaped upon packet // reception. ASSERT_EQ(json_packet, delegate.structured_data_packets[0]); }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("qPlatform_mkdir:")); mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX); if (packet.GetChar() == ',') { std::string path; packet.GetHexByteString(path); Error error = FileSystem::MakeDirectory(FileSpec{path, false}, mode); StreamGDBRemote response; response.Printf("F%u", error.GetError()); return SendPacketNoLock(response.GetString()); } return SendErrorResponse(20); }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("vFile:MD5:")); std::string path; packet.GetHexByteString(path); if (!path.empty()) { uint64_t a,b; StreamGDBRemote response; if (Host::CalculateMD5(FileSpec(path.c_str(),false),a,b) == false) { response.PutCString("F,"); response.PutCString("x"); } else { response.PutCString("F,"); response.PutHex64(a); response.PutHex64(b); } return SendPacketNoLock(response.GetData(), response.GetSize()); } return SendErrorResponse(25); }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet) { #ifdef _WIN32 return SendErrorResponse(9); #else // Spawn a local debugserver as a platform so we can then attach or launch // a process... Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); if (log) log->Printf ("GDBRemoteCommunicationServerPlatform::%s() called", __FUNCTION__); ConnectionFileDescriptor file_conn; std::string hostname; packet.SetFilePos(::strlen ("qLaunchGDBServer;")); std::string name; std::string value; uint16_t port = UINT16_MAX; while (packet.GetNameColonValue(name, value)) { if (name.compare ("host") == 0) hostname.swap(value); else if (name.compare ("port") == 0) port = StringConvert::ToUInt32(value.c_str(), 0, 0); } lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; std::string socket_name; Error error = LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ()); return SendErrorResponse(9); } if (log) log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid); StreamGDBRemote response; response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset); if (!socket_name.empty()) { response.PutCString("socket_name:"); response.PutCStringAsRawHex8(socket_name.c_str()); response.PutChar(';'); } PacketResult packet_result = SendPacketNoLock(response.GetData(), response.GetSize()); if (packet_result != PacketResult::Success) { if (debugserver_pid != LLDB_INVALID_PROCESS_ID) ::kill (debugserver_pid, SIGINT); } return packet_result; #endif }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod (StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("qPlatform_chmod:")); mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX); if (packet.GetChar() == ',') { std::string path; packet.GetHexByteString(path); Error error = FileSystem::SetFilePermissions(FileSpec{path, true}, mode); StreamGDBRemote response; response.Printf("F%u", error.GetError()); return SendPacketNoLock(response.GetData(), response.GetSize()); } return SendErrorResponse(19); }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite( StringExtractorGDBRemote &packet) { #ifdef _WIN32 return SendUnimplementedResponse("GDBRemoteCommunicationServerCommon::Handle_" "vFile_pWrite() unimplemented"); #else packet.SetFilePos(::strlen("vFile:pwrite:")); StreamGDBRemote response; response.PutChar('F'); int fd = packet.GetU32(UINT32_MAX); if (packet.GetChar() == ',') { off_t offset = packet.GetU64(UINT32_MAX); if (packet.GetChar() == ',') { std::string buffer; if (packet.GetEscapedBinaryData(buffer)) { const ssize_t bytes_written = ::pwrite(fd, buffer.data(), buffer.size(), offset); const int save_errno = bytes_written == -1 ? errno : 0; response.Printf("%zi", bytes_written); if (save_errno) response.Printf(",%i", save_errno); } else { response.Printf("-1,%i", EINVAL); } return SendPacketNoLock(response.GetString()); } } return SendErrorResponse(27); #endif }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qSupported (StringExtractorGDBRemote &packet) { StreamGDBRemote response; // Features common to lldb-platform and llgs. uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet size--debugger can always use less response.Printf ("PacketSize=%x", max_packet_size); response.PutCString (";QStartNoAckMode+"); response.PutCString (";QThreadSuffixSupported+"); response.PutCString (";QListThreadsInStopReply+"); response.PutCString (";qEcho+"); #if defined(__linux__) response.PutCString (";qXfer:auxv:read+"); #endif return SendPacketNoLock(response.GetData(), response.GetSize()); }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("qPlatform_shell:")); std::string path; std::string working_dir; packet.GetHexByteStringTerminatedBy(path, ','); if (!path.empty()) { if (packet.GetChar() == ',') { // FIXME: add timeout to qPlatform_shell packet // uint32_t timeout = packet.GetHexMaxU32(false, 32); uint32_t timeout = 10; if (packet.GetChar() == ',') packet.GetHexByteString(working_dir); int status, signo; std::string output; Error err = Host::RunShellCommand(path.c_str(), FileSpec{working_dir, true}, &status, &signo, &output, timeout); StreamGDBRemote response; if (err.Fail()) { response.PutCString("F,"); response.PutHex32(UINT32_MAX); } else { response.PutCString("F,"); response.PutHex32(status); response.PutChar(','); response.PutHex32(signo); response.PutChar(','); response.PutEscapedBytes(output.c_str(), output.size()); } return SendPacketNoLock(response.GetString()); } } return SendErrorResponse(24); }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_pRead( StringExtractorGDBRemote &packet) { #ifdef _WIN32 // Not implemented on Windows return SendUnimplementedResponse( "GDBRemoteCommunicationServerCommon::Handle_vFile_pRead() unimplemented"); #else StreamGDBRemote response; packet.SetFilePos(::strlen("vFile:pread:")); int fd = packet.GetS32(-1); if (packet.GetChar() == ',') { uint64_t count = packet.GetU64(UINT64_MAX); if (packet.GetChar() == ',') { uint64_t offset = packet.GetU64(UINT32_MAX); if (count == UINT64_MAX) { response.Printf("F-1:%i", EINVAL); return SendPacketNoLock(response.GetString()); } std::string buffer(count, 0); const ssize_t bytes_read = ::pread(fd, &buffer[0], buffer.size(), offset); const int save_errno = bytes_read == -1 ? errno : 0; response.PutChar('F'); response.Printf("%zi", bytes_read); if (save_errno) response.Printf(",%i", save_errno); else { response.PutChar(';'); response.PutEscapedBytes(&buffer[0], bytes_read); } return SendPacketNoLock(response.GetString()); } } return SendErrorResponse(21); #endif }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qModuleInfo( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("qModuleInfo:")); std::string module_path; packet.GetHexByteStringTerminatedBy(module_path, ';'); if (module_path.empty()) return SendErrorResponse(1); if (packet.GetChar() != ';') return SendErrorResponse(2); std::string triple; packet.GetHexByteString(triple); ModuleSpec matched_module_spec = GetModuleInfo(module_path, triple); if (!matched_module_spec.GetFileSpec()) return SendErrorResponse(3); const auto file_offset = matched_module_spec.GetObjectOffset(); const auto file_size = matched_module_spec.GetObjectSize(); const auto uuid_str = matched_module_spec.GetUUID().GetAsString(""); StreamGDBRemote response; if (uuid_str.empty()) { std::string md5_hash; if (!FileSystem::CalculateMD5AsString(matched_module_spec.GetFileSpec(), file_offset, file_size, md5_hash)) return SendErrorResponse(5); response.PutCString("md5:"); response.PutCStringAsRawHex8(md5_hash.c_str()); } else { response.PutCString("uuid:"); response.PutCStringAsRawHex8(uuid_str.c_str()); } response.PutChar(';'); const auto &module_arch = matched_module_spec.GetArchitecture(); response.PutCString("triple:"); response.PutCStringAsRawHex8(module_arch.GetTriple().getTriple().c_str()); response.PutChar(';'); response.PutCString("file_path:"); response.PutCStringAsRawHex8(matched_module_spec.GetFileSpec().GetCString()); response.PutChar(';'); response.PutCString("file_offset:"); response.PutHex64(file_offset); response.PutChar(';'); response.PutCString("file_size:"); response.PutHex64(file_size); response.PutChar(';'); return SendPacketNoLock(response.GetString()); }