15ffd83dbSDimitry Andric //===-- GDBRemoteCommunicationServerCommon.cpp ----------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "GDBRemoteCommunicationServerCommon.h"
100b57cec5SDimitry Andric 
11fe6060f1SDimitry Andric #include <cerrno>
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifdef __APPLE__
140b57cec5SDimitry Andric #include <TargetConditionals.h>
150b57cec5SDimitry Andric #endif
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include <chrono>
180b57cec5SDimitry Andric #include <cstring>
19bdd1243dSDimitry Andric #include <optional>
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric #include "lldb/Core/ModuleSpec.h"
220b57cec5SDimitry Andric #include "lldb/Host/Config.h"
230b57cec5SDimitry Andric #include "lldb/Host/File.h"
240b57cec5SDimitry Andric #include "lldb/Host/FileAction.h"
250b57cec5SDimitry Andric #include "lldb/Host/FileSystem.h"
260b57cec5SDimitry Andric #include "lldb/Host/Host.h"
270b57cec5SDimitry Andric #include "lldb/Host/HostInfo.h"
280b57cec5SDimitry Andric #include "lldb/Host/SafeMachO.h"
290b57cec5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h"
300b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h"
310b57cec5SDimitry Andric #include "lldb/Target/Platform.h"
320b57cec5SDimitry Andric #include "lldb/Utility/Endian.h"
339dba64beSDimitry Andric #include "lldb/Utility/GDBRemote.h"
3481ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
350b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
360b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
370b57cec5SDimitry Andric #include "lldb/Utility/StructuredData.h"
389dba64beSDimitry Andric #include "llvm/ADT/StringSwitch.h"
399dba64beSDimitry Andric #include "llvm/Support/JSON.h"
4006c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric #include "ProcessGDBRemoteLog.h"
430b57cec5SDimitry Andric #include "lldb/Utility/StringExtractorGDBRemote.h"
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric #ifdef __ANDROID__
460b57cec5SDimitry Andric #include "lldb/Host/android/HostInfoAndroid.h"
4706c3fb27SDimitry Andric #include "lldb/Host/common/ZipFileResolver.h"
480b57cec5SDimitry Andric #endif
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric using namespace lldb;
510b57cec5SDimitry Andric using namespace lldb_private::process_gdb_remote;
529dba64beSDimitry Andric using namespace lldb_private;
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric #ifdef __ANDROID__
550b57cec5SDimitry Andric const static uint32_t g_default_packet_timeout_sec = 20; // seconds
560b57cec5SDimitry Andric #else
570b57cec5SDimitry Andric const static uint32_t g_default_packet_timeout_sec = 0; // not specified
580b57cec5SDimitry Andric #endif
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric // GDBRemoteCommunicationServerCommon constructor
61bdd1243dSDimitry Andric GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon()
62bdd1243dSDimitry Andric     : GDBRemoteCommunicationServer(), m_process_launch_info(),
63bdd1243dSDimitry Andric       m_process_launch_error(), m_proc_infos(), m_proc_infos_index(0) {
640b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_A,
650b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerCommon::Handle_A);
660b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
670b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QEnvironment,
680b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_QEnvironment);
690b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
700b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QEnvironmentHexEncoded,
710b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded);
720b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
730b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qfProcessInfo,
740b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo);
750b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
760b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qGroupName,
770b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qGroupName);
780b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
790b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qHostInfo,
800b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qHostInfo);
810b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
820b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QLaunchArch,
830b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_QLaunchArch);
840b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
850b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess,
860b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess);
870b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
880b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qEcho,
890b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qEcho);
900b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
910b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qModuleInfo,
920b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qModuleInfo);
930b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
940b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_jModulesInfo,
950b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_jModulesInfo);
960b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
970b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod,
980b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod);
990b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1000b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir,
1010b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir);
1020b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1030b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qPlatform_shell,
1040b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell);
1050b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1060b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID,
1070b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qProcessInfoPID);
1080b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1090b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QSetDetachOnError,
1100b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError);
1110b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1120b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QSetSTDERR,
1130b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR);
1140b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1150b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QSetSTDIN,
1160b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN);
1170b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1180b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT,
1190b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT);
1200b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1210b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qSpeedTest,
1220b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qSpeedTest);
1230b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1240b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qsProcessInfo,
1250b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo);
1260b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1270b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode,
1280b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode);
1290b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1300b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qSupported,
1310b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qSupported);
1320b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1330b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qUserName,
1340b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qUserName);
1350b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1360b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_close,
1370b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_Close);
1380b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1390b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_exists,
1400b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_Exists);
1410b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1420b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_md5,
1430b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_MD5);
1440b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1450b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_mode,
1460b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_Mode);
1470b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1480b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_open,
1490b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_Open);
1500b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1510b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_pread,
1520b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_pRead);
1530b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1540b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_pwrite,
1550b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite);
1560b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1570b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_size,
1580b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_Size);
1590b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
160349cc55cSDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_fstat,
161349cc55cSDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_FStat);
162349cc55cSDimitry Andric   RegisterMemberFunctionHandler(
1630b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_stat,
1640b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_Stat);
1650b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1660b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_symlink,
1670b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_symlink);
1680b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1690b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_unlink,
1700b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_unlink);
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric // Destructor
174fe6060f1SDimitry Andric GDBRemoteCommunicationServerCommon::~GDBRemoteCommunicationServerCommon() =
175fe6060f1SDimitry Andric     default;
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
1780b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qHostInfo(
1790b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
1800b57cec5SDimitry Andric   StreamString response;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric   ArchSpec host_arch(HostInfo::GetArchitecture());
1850b57cec5SDimitry Andric   const llvm::Triple &host_triple = host_arch.GetTriple();
1860b57cec5SDimitry Andric   response.PutCString("triple:");
1870b57cec5SDimitry Andric   response.PutStringAsRawHex8(host_triple.getTriple());
1880b57cec5SDimitry Andric   response.Printf(";ptrsize:%u;", host_arch.GetAddressByteSize());
1890b57cec5SDimitry Andric 
19006c3fb27SDimitry Andric   llvm::StringRef distribution_id = HostInfo::GetDistributionId();
19106c3fb27SDimitry Andric   if (!distribution_id.empty()) {
1920b57cec5SDimitry Andric     response.PutCString("distribution_id:");
1930b57cec5SDimitry Andric     response.PutStringAsRawHex8(distribution_id);
1940b57cec5SDimitry Andric     response.PutCString(";");
1950b57cec5SDimitry Andric   }
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric #if defined(__APPLE__)
1980b57cec5SDimitry Andric   // For parity with debugserver, we'll include the vendor key.
1990b57cec5SDimitry Andric   response.PutCString("vendor:apple;");
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric   // Send out MachO info.
2020b57cec5SDimitry Andric   uint32_t cpu = host_arch.GetMachOCPUType();
2030b57cec5SDimitry Andric   uint32_t sub = host_arch.GetMachOCPUSubType();
2040b57cec5SDimitry Andric   if (cpu != LLDB_INVALID_CPUTYPE)
2050b57cec5SDimitry Andric     response.Printf("cputype:%u;", cpu);
2060b57cec5SDimitry Andric   if (sub != LLDB_INVALID_CPUTYPE)
2070b57cec5SDimitry Andric     response.Printf("cpusubtype:%u;", sub);
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric   if (cpu == llvm::MachO::CPU_TYPE_ARM || cpu == llvm::MachO::CPU_TYPE_ARM64) {
2100b57cec5SDimitry Andric // Indicate the OS type.
2110b57cec5SDimitry Andric #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
2120b57cec5SDimitry Andric     response.PutCString("ostype:tvos;");
2130b57cec5SDimitry Andric #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
2140b57cec5SDimitry Andric     response.PutCString("ostype:watchos;");
2150b57cec5SDimitry Andric #elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
2160b57cec5SDimitry Andric     response.PutCString("ostype:bridgeos;");
2170b57cec5SDimitry Andric #else
2180b57cec5SDimitry Andric     response.PutCString("ostype:ios;");
2190b57cec5SDimitry Andric #endif
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric     // On arm, we use "synchronous" watchpoints which means the exception is
2220b57cec5SDimitry Andric     // delivered before the instruction executes.
2230b57cec5SDimitry Andric     response.PutCString("watchpoint_exceptions_received:before;");
2240b57cec5SDimitry Andric   } else {
2250b57cec5SDimitry Andric     response.PutCString("ostype:macosx;");
2260b57cec5SDimitry Andric     response.Printf("watchpoint_exceptions_received:after;");
2270b57cec5SDimitry Andric   }
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric #else
2300b57cec5SDimitry Andric   if (host_arch.GetMachine() == llvm::Triple::aarch64 ||
2319dba64beSDimitry Andric       host_arch.GetMachine() == llvm::Triple::aarch64_32 ||
2320b57cec5SDimitry Andric       host_arch.GetMachine() == llvm::Triple::aarch64_be ||
2330b57cec5SDimitry Andric       host_arch.GetMachine() == llvm::Triple::arm ||
2340b57cec5SDimitry Andric       host_arch.GetMachine() == llvm::Triple::armeb || host_arch.IsMIPS())
2350b57cec5SDimitry Andric     response.Printf("watchpoint_exceptions_received:before;");
2360b57cec5SDimitry Andric   else
2370b57cec5SDimitry Andric     response.Printf("watchpoint_exceptions_received:after;");
2380b57cec5SDimitry Andric #endif
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   switch (endian::InlHostByteOrder()) {
2410b57cec5SDimitry Andric   case eByteOrderBig:
2420b57cec5SDimitry Andric     response.PutCString("endian:big;");
2430b57cec5SDimitry Andric     break;
2440b57cec5SDimitry Andric   case eByteOrderLittle:
2450b57cec5SDimitry Andric     response.PutCString("endian:little;");
2460b57cec5SDimitry Andric     break;
2470b57cec5SDimitry Andric   case eByteOrderPDP:
2480b57cec5SDimitry Andric     response.PutCString("endian:pdp;");
2490b57cec5SDimitry Andric     break;
2500b57cec5SDimitry Andric   default:
2510b57cec5SDimitry Andric     response.PutCString("endian:unknown;");
2520b57cec5SDimitry Andric     break;
2530b57cec5SDimitry Andric   }
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   llvm::VersionTuple version = HostInfo::GetOSVersion();
2560b57cec5SDimitry Andric   if (!version.empty()) {
2570b57cec5SDimitry Andric     response.Format("os_version:{0}", version.getAsString());
2580b57cec5SDimitry Andric     response.PutChar(';');
2590b57cec5SDimitry Andric   }
2600b57cec5SDimitry Andric 
2619dba64beSDimitry Andric #if defined(__APPLE__)
2629dba64beSDimitry Andric   llvm::VersionTuple maccatalyst_version = HostInfo::GetMacCatalystVersion();
2639dba64beSDimitry Andric   if (!maccatalyst_version.empty()) {
2649dba64beSDimitry Andric     response.Format("maccatalyst_version:{0}",
2659dba64beSDimitry Andric                     maccatalyst_version.getAsString());
2669dba64beSDimitry Andric     response.PutChar(';');
2679dba64beSDimitry Andric   }
2689dba64beSDimitry Andric #endif
2699dba64beSDimitry Andric 
270bdd1243dSDimitry Andric   if (std::optional<std::string> s = HostInfo::GetOSBuildString()) {
2710b57cec5SDimitry Andric     response.PutCString("os_build:");
272349cc55cSDimitry Andric     response.PutStringAsRawHex8(*s);
2730b57cec5SDimitry Andric     response.PutChar(';');
2740b57cec5SDimitry Andric   }
275bdd1243dSDimitry Andric   if (std::optional<std::string> s = HostInfo::GetOSKernelDescription()) {
2760b57cec5SDimitry Andric     response.PutCString("os_kernel:");
277349cc55cSDimitry Andric     response.PutStringAsRawHex8(*s);
2780b57cec5SDimitry Andric     response.PutChar(';');
2790b57cec5SDimitry Andric   }
2800b57cec5SDimitry Andric 
281349cc55cSDimitry Andric   std::string s;
2820b57cec5SDimitry Andric #if defined(__APPLE__)
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
2850b57cec5SDimitry Andric   // For iOS devices, we are connected through a USB Mux so we never pretend to
2860b57cec5SDimitry Andric   // actually have a hostname as far as the remote lldb that is connecting to
2870b57cec5SDimitry Andric   // this lldb-platform is concerned
2880b57cec5SDimitry Andric   response.PutCString("hostname:");
2890b57cec5SDimitry Andric   response.PutStringAsRawHex8("127.0.0.1");
2900b57cec5SDimitry Andric   response.PutChar(';');
2910b57cec5SDimitry Andric #else  // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
2920b57cec5SDimitry Andric   if (HostInfo::GetHostname(s)) {
2930b57cec5SDimitry Andric     response.PutCString("hostname:");
2940b57cec5SDimitry Andric     response.PutStringAsRawHex8(s);
2950b57cec5SDimitry Andric     response.PutChar(';');
2960b57cec5SDimitry Andric   }
2970b57cec5SDimitry Andric #endif // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric #else  // #if defined(__APPLE__)
3000b57cec5SDimitry Andric   if (HostInfo::GetHostname(s)) {
3010b57cec5SDimitry Andric     response.PutCString("hostname:");
3020b57cec5SDimitry Andric     response.PutStringAsRawHex8(s);
3030b57cec5SDimitry Andric     response.PutChar(';');
3040b57cec5SDimitry Andric   }
3050b57cec5SDimitry Andric #endif // #if defined(__APPLE__)
306bdd1243dSDimitry Andric   // coverity[unsigned_compare]
3070b57cec5SDimitry Andric   if (g_default_packet_timeout_sec > 0)
3080b57cec5SDimitry Andric     response.Printf("default_packet_timeout:%u;", g_default_packet_timeout_sec);
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
3140b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qProcessInfoPID(
3150b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
3160b57cec5SDimitry Andric   // Packet format: "qProcessInfoPID:%i" where %i is the pid
3170b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qProcessInfoPID:"));
3180b57cec5SDimitry Andric   lldb::pid_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID);
3190b57cec5SDimitry Andric   if (pid != LLDB_INVALID_PROCESS_ID) {
3200b57cec5SDimitry Andric     ProcessInstanceInfo proc_info;
3210b57cec5SDimitry Andric     if (Host::GetProcessInfo(pid, proc_info)) {
3220b57cec5SDimitry Andric       StreamString response;
3230b57cec5SDimitry Andric       CreateProcessInfoResponse(proc_info, response);
3240b57cec5SDimitry Andric       return SendPacketNoLock(response.GetString());
3250b57cec5SDimitry Andric     }
3260b57cec5SDimitry Andric   }
3270b57cec5SDimitry Andric   return SendErrorResponse(1);
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
3310b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo(
3320b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
3330b57cec5SDimitry Andric   m_proc_infos_index = 0;
3345ffd83dbSDimitry Andric   m_proc_infos.clear();
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric   ProcessInstanceInfoMatch match_info;
3370b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qfProcessInfo"));
3380b57cec5SDimitry Andric   if (packet.GetChar() == ':') {
3390b57cec5SDimitry Andric     llvm::StringRef key;
3400b57cec5SDimitry Andric     llvm::StringRef value;
3410b57cec5SDimitry Andric     while (packet.GetNameColonValue(key, value)) {
3420b57cec5SDimitry Andric       bool success = true;
343*0fca6ea1SDimitry Andric       if (key == "name") {
3440b57cec5SDimitry Andric         StringExtractor extractor(value);
3450b57cec5SDimitry Andric         std::string file;
3460b57cec5SDimitry Andric         extractor.GetHexByteString(file);
3470b57cec5SDimitry Andric         match_info.GetProcessInfo().GetExecutableFile().SetFile(
3480b57cec5SDimitry Andric             file, FileSpec::Style::native);
349*0fca6ea1SDimitry Andric       } else if (key == "name_match") {
3500b57cec5SDimitry Andric         NameMatch name_match = llvm::StringSwitch<NameMatch>(value)
3510b57cec5SDimitry Andric                                    .Case("equals", NameMatch::Equals)
3520b57cec5SDimitry Andric                                    .Case("starts_with", NameMatch::StartsWith)
3530b57cec5SDimitry Andric                                    .Case("ends_with", NameMatch::EndsWith)
3540b57cec5SDimitry Andric                                    .Case("contains", NameMatch::Contains)
3550b57cec5SDimitry Andric                                    .Case("regex", NameMatch::RegularExpression)
3560b57cec5SDimitry Andric                                    .Default(NameMatch::Ignore);
3570b57cec5SDimitry Andric         match_info.SetNameMatchType(name_match);
3580b57cec5SDimitry Andric         if (name_match == NameMatch::Ignore)
3590b57cec5SDimitry Andric           return SendErrorResponse(2);
360*0fca6ea1SDimitry Andric       } else if (key == "pid") {
3610b57cec5SDimitry Andric         lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
3620b57cec5SDimitry Andric         if (value.getAsInteger(0, pid))
3630b57cec5SDimitry Andric           return SendErrorResponse(2);
3640b57cec5SDimitry Andric         match_info.GetProcessInfo().SetProcessID(pid);
365*0fca6ea1SDimitry Andric       } else if (key == "parent_pid") {
3660b57cec5SDimitry Andric         lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
3670b57cec5SDimitry Andric         if (value.getAsInteger(0, pid))
3680b57cec5SDimitry Andric           return SendErrorResponse(2);
3690b57cec5SDimitry Andric         match_info.GetProcessInfo().SetParentProcessID(pid);
370*0fca6ea1SDimitry Andric       } else if (key == "uid") {
3710b57cec5SDimitry Andric         uint32_t uid = UINT32_MAX;
3720b57cec5SDimitry Andric         if (value.getAsInteger(0, uid))
3730b57cec5SDimitry Andric           return SendErrorResponse(2);
3740b57cec5SDimitry Andric         match_info.GetProcessInfo().SetUserID(uid);
375*0fca6ea1SDimitry Andric       } else if (key == "gid") {
3760b57cec5SDimitry Andric         uint32_t gid = UINT32_MAX;
3770b57cec5SDimitry Andric         if (value.getAsInteger(0, gid))
3780b57cec5SDimitry Andric           return SendErrorResponse(2);
3790b57cec5SDimitry Andric         match_info.GetProcessInfo().SetGroupID(gid);
380*0fca6ea1SDimitry Andric       } else if (key == "euid") {
3810b57cec5SDimitry Andric         uint32_t uid = UINT32_MAX;
3820b57cec5SDimitry Andric         if (value.getAsInteger(0, uid))
3830b57cec5SDimitry Andric           return SendErrorResponse(2);
3840b57cec5SDimitry Andric         match_info.GetProcessInfo().SetEffectiveUserID(uid);
385*0fca6ea1SDimitry Andric       } else if (key == "egid") {
3860b57cec5SDimitry Andric         uint32_t gid = UINT32_MAX;
3870b57cec5SDimitry Andric         if (value.getAsInteger(0, gid))
3880b57cec5SDimitry Andric           return SendErrorResponse(2);
3890b57cec5SDimitry Andric         match_info.GetProcessInfo().SetEffectiveGroupID(gid);
390*0fca6ea1SDimitry Andric       } else if (key == "all_users") {
3910b57cec5SDimitry Andric         match_info.SetMatchAllUsers(
3920b57cec5SDimitry Andric             OptionArgParser::ToBoolean(value, false, &success));
393*0fca6ea1SDimitry Andric       } else if (key == "triple") {
3940b57cec5SDimitry Andric         match_info.GetProcessInfo().GetArchitecture() =
3950b57cec5SDimitry Andric             HostInfo::GetAugmentedArchSpec(value);
3960b57cec5SDimitry Andric       } else {
3970b57cec5SDimitry Andric         success = false;
3980b57cec5SDimitry Andric       }
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric       if (!success)
4010b57cec5SDimitry Andric         return SendErrorResponse(2);
4020b57cec5SDimitry Andric     }
4030b57cec5SDimitry Andric   }
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric   if (Host::FindProcesses(match_info, m_proc_infos)) {
4060b57cec5SDimitry Andric     // We found something, return the first item by calling the get subsequent
4070b57cec5SDimitry Andric     // process info packet handler...
4080b57cec5SDimitry Andric     return Handle_qsProcessInfo(packet);
4090b57cec5SDimitry Andric   }
4100b57cec5SDimitry Andric   return SendErrorResponse(3);
4110b57cec5SDimitry Andric }
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
4140b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo(
4150b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
4165ffd83dbSDimitry Andric   if (m_proc_infos_index < m_proc_infos.size()) {
4170b57cec5SDimitry Andric     StreamString response;
4185ffd83dbSDimitry Andric     CreateProcessInfoResponse(m_proc_infos[m_proc_infos_index], response);
4190b57cec5SDimitry Andric     ++m_proc_infos_index;
4200b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
4210b57cec5SDimitry Andric   }
4220b57cec5SDimitry Andric   return SendErrorResponse(4);
4230b57cec5SDimitry Andric }
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
4260b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qUserName(
4270b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
428480093f4SDimitry Andric #if LLDB_ENABLE_POSIX
42981ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
4309dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__);
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric   // Packet format: "qUserName:%i" where %i is the uid
4330b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qUserName:"));
4340b57cec5SDimitry Andric   uint32_t uid = packet.GetU32(UINT32_MAX);
4350b57cec5SDimitry Andric   if (uid != UINT32_MAX) {
436bdd1243dSDimitry Andric     if (std::optional<llvm::StringRef> name =
4370b57cec5SDimitry Andric             HostInfo::GetUserIDResolver().GetUserName(uid)) {
4380b57cec5SDimitry Andric       StreamString response;
4390b57cec5SDimitry Andric       response.PutStringAsRawHex8(*name);
4400b57cec5SDimitry Andric       return SendPacketNoLock(response.GetString());
4410b57cec5SDimitry Andric     }
4420b57cec5SDimitry Andric   }
4439dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerCommon::%s end", __FUNCTION__);
4440b57cec5SDimitry Andric #endif
4450b57cec5SDimitry Andric   return SendErrorResponse(5);
4460b57cec5SDimitry Andric }
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
4490b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qGroupName(
4500b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
451480093f4SDimitry Andric #if LLDB_ENABLE_POSIX
4520b57cec5SDimitry Andric   // Packet format: "qGroupName:%i" where %i is the gid
4530b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qGroupName:"));
4540b57cec5SDimitry Andric   uint32_t gid = packet.GetU32(UINT32_MAX);
4550b57cec5SDimitry Andric   if (gid != UINT32_MAX) {
456bdd1243dSDimitry Andric     if (std::optional<llvm::StringRef> name =
4570b57cec5SDimitry Andric             HostInfo::GetUserIDResolver().GetGroupName(gid)) {
4580b57cec5SDimitry Andric       StreamString response;
4590b57cec5SDimitry Andric       response.PutStringAsRawHex8(*name);
4600b57cec5SDimitry Andric       return SendPacketNoLock(response.GetString());
4610b57cec5SDimitry Andric     }
4620b57cec5SDimitry Andric   }
4630b57cec5SDimitry Andric #endif
4640b57cec5SDimitry Andric   return SendErrorResponse(6);
4650b57cec5SDimitry Andric }
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
4680b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qSpeedTest(
4690b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
4700b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qSpeedTest:"));
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric   llvm::StringRef key;
4730b57cec5SDimitry Andric   llvm::StringRef value;
4740b57cec5SDimitry Andric   bool success = packet.GetNameColonValue(key, value);
475*0fca6ea1SDimitry Andric   if (success && key == "response_size") {
4760b57cec5SDimitry Andric     uint32_t response_size = 0;
4770b57cec5SDimitry Andric     if (!value.getAsInteger(0, response_size)) {
4780b57cec5SDimitry Andric       if (response_size == 0)
4790b57cec5SDimitry Andric         return SendOKResponse();
4800b57cec5SDimitry Andric       StreamString response;
4810b57cec5SDimitry Andric       uint32_t bytes_left = response_size;
4820b57cec5SDimitry Andric       response.PutCString("data:");
4830b57cec5SDimitry Andric       while (bytes_left > 0) {
4840b57cec5SDimitry Andric         if (bytes_left >= 26) {
4850b57cec5SDimitry Andric           response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
4860b57cec5SDimitry Andric           bytes_left -= 26;
4870b57cec5SDimitry Andric         } else {
4880b57cec5SDimitry Andric           response.Printf("%*.*s;", bytes_left, bytes_left,
4890b57cec5SDimitry Andric                           "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
4900b57cec5SDimitry Andric           bytes_left = 0;
4910b57cec5SDimitry Andric         }
4920b57cec5SDimitry Andric       }
4930b57cec5SDimitry Andric       return SendPacketNoLock(response.GetString());
4940b57cec5SDimitry Andric     }
4950b57cec5SDimitry Andric   }
4960b57cec5SDimitry Andric   return SendErrorResponse(7);
4970b57cec5SDimitry Andric }
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
5000b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_Open(
5010b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
5020b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:open:"));
5030b57cec5SDimitry Andric   std::string path;
5040b57cec5SDimitry Andric   packet.GetHexByteStringTerminatedBy(path, ',');
5050b57cec5SDimitry Andric   if (!path.empty()) {
5060b57cec5SDimitry Andric     if (packet.GetChar() == ',') {
5079dba64beSDimitry Andric       auto flags = File::OpenOptions(packet.GetHexMaxU32(false, 0));
5080b57cec5SDimitry Andric       if (packet.GetChar() == ',') {
5090b57cec5SDimitry Andric         mode_t mode = packet.GetHexMaxU32(false, 0600);
5100b57cec5SDimitry Andric         FileSpec path_spec(path);
5110b57cec5SDimitry Andric         FileSystem::Instance().Resolve(path_spec);
5120b57cec5SDimitry Andric         // Do not close fd.
5139dba64beSDimitry Andric         auto file = FileSystem::Instance().Open(path_spec, flags, mode, false);
5149dba64beSDimitry Andric 
515349cc55cSDimitry Andric         StreamString response;
516349cc55cSDimitry Andric         response.PutChar('F');
517349cc55cSDimitry Andric 
5189dba64beSDimitry Andric         int descriptor = File::kInvalidDescriptor;
5199dba64beSDimitry Andric         if (file) {
5209dba64beSDimitry Andric           descriptor = file.get()->GetDescriptor();
521349cc55cSDimitry Andric           response.Printf("%x", descriptor);
5229dba64beSDimitry Andric         } else {
523349cc55cSDimitry Andric           response.PutCString("-1");
5249dba64beSDimitry Andric           std::error_code code = errorToErrorCode(file.takeError());
5259dba64beSDimitry Andric           if (code.category() == std::system_category()) {
526349cc55cSDimitry Andric             response.Printf(",%x", code.value());
5279dba64beSDimitry Andric           }
5289dba64beSDimitry Andric         }
5299dba64beSDimitry Andric 
5300b57cec5SDimitry Andric         return SendPacketNoLock(response.GetString());
5310b57cec5SDimitry Andric       }
5320b57cec5SDimitry Andric     }
5330b57cec5SDimitry Andric   }
5340b57cec5SDimitry Andric   return SendErrorResponse(18);
5350b57cec5SDimitry Andric }
5360b57cec5SDimitry Andric 
537349cc55cSDimitry Andric static GDBErrno system_errno_to_gdb(int err) {
538349cc55cSDimitry Andric   switch (err) {
539349cc55cSDimitry Andric #define HANDLE_ERRNO(name, value)                                              \
540349cc55cSDimitry Andric   case name:                                                                   \
541349cc55cSDimitry Andric     return GDB_##name;
542349cc55cSDimitry Andric #include "Plugins/Process/gdb-remote/GDBRemoteErrno.def"
543349cc55cSDimitry Andric   default:
544349cc55cSDimitry Andric     return GDB_EUNKNOWN;
545349cc55cSDimitry Andric   }
546349cc55cSDimitry Andric }
547349cc55cSDimitry Andric 
5480b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
5490b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_Close(
5500b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
5510b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:close:"));
552349cc55cSDimitry Andric   int fd = packet.GetS32(-1, 16);
5530b57cec5SDimitry Andric   int err = -1;
5540b57cec5SDimitry Andric   int save_errno = 0;
5550b57cec5SDimitry Andric   if (fd >= 0) {
5569dba64beSDimitry Andric     NativeFile file(fd, File::OpenOptions(0), true);
5570b57cec5SDimitry Andric     Status error = file.Close();
5580b57cec5SDimitry Andric     err = 0;
5590b57cec5SDimitry Andric     save_errno = error.GetError();
5600b57cec5SDimitry Andric   } else {
5610b57cec5SDimitry Andric     save_errno = EINVAL;
5620b57cec5SDimitry Andric   }
5630b57cec5SDimitry Andric   StreamString response;
5640b57cec5SDimitry Andric   response.PutChar('F');
565349cc55cSDimitry Andric   response.Printf("%x", err);
5660b57cec5SDimitry Andric   if (save_errno)
567349cc55cSDimitry Andric     response.Printf(",%x", system_errno_to_gdb(save_errno));
5680b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
5690b57cec5SDimitry Andric }
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
5720b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_pRead(
5730b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
5740b57cec5SDimitry Andric   StreamGDBRemote response;
5750b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:pread:"));
576349cc55cSDimitry Andric   int fd = packet.GetS32(-1, 16);
5770b57cec5SDimitry Andric   if (packet.GetChar() == ',') {
578349cc55cSDimitry Andric     size_t count = packet.GetHexMaxU64(false, SIZE_MAX);
5790b57cec5SDimitry Andric     if (packet.GetChar() == ',') {
580349cc55cSDimitry Andric       off_t offset = packet.GetHexMaxU32(false, UINT32_MAX);
5819dba64beSDimitry Andric       if (count == SIZE_MAX) {
582349cc55cSDimitry Andric         response.Printf("F-1:%x", EINVAL);
5830b57cec5SDimitry Andric         return SendPacketNoLock(response.GetString());
5840b57cec5SDimitry Andric       }
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric       std::string buffer(count, 0);
587349cc55cSDimitry Andric       NativeFile file(fd, File::eOpenOptionReadOnly, false);
5880b57cec5SDimitry Andric       Status error = file.Read(static_cast<void *>(&buffer[0]), count, offset);
5890b57cec5SDimitry Andric       const int save_errno = error.GetError();
5900b57cec5SDimitry Andric       response.PutChar('F');
591349cc55cSDimitry Andric       if (error.Success()) {
592349cc55cSDimitry Andric         response.Printf("%zx", count);
5930b57cec5SDimitry Andric         response.PutChar(';');
594349cc55cSDimitry Andric         response.PutEscapedBytes(&buffer[0], count);
595349cc55cSDimitry Andric       } else {
596349cc55cSDimitry Andric         response.PutCString("-1");
597349cc55cSDimitry Andric         if (save_errno)
598349cc55cSDimitry Andric           response.Printf(",%x", system_errno_to_gdb(save_errno));
5990b57cec5SDimitry Andric       }
6000b57cec5SDimitry Andric       return SendPacketNoLock(response.GetString());
6010b57cec5SDimitry Andric     }
6020b57cec5SDimitry Andric   }
6030b57cec5SDimitry Andric   return SendErrorResponse(21);
6040b57cec5SDimitry Andric }
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
6070b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite(
6080b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
6090b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:pwrite:"));
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric   StreamGDBRemote response;
6120b57cec5SDimitry Andric   response.PutChar('F');
6130b57cec5SDimitry Andric 
614349cc55cSDimitry Andric   int fd = packet.GetS32(-1, 16);
6150b57cec5SDimitry Andric   if (packet.GetChar() == ',') {
616349cc55cSDimitry Andric     off_t offset = packet.GetHexMaxU32(false, UINT32_MAX);
6170b57cec5SDimitry Andric     if (packet.GetChar() == ',') {
6180b57cec5SDimitry Andric       std::string buffer;
6190b57cec5SDimitry Andric       if (packet.GetEscapedBinaryData(buffer)) {
620349cc55cSDimitry Andric         NativeFile file(fd, File::eOpenOptionWriteOnly, false);
6210b57cec5SDimitry Andric         size_t count = buffer.size();
6220b57cec5SDimitry Andric         Status error =
6230b57cec5SDimitry Andric             file.Write(static_cast<const void *>(&buffer[0]), count, offset);
6240b57cec5SDimitry Andric         const int save_errno = error.GetError();
625349cc55cSDimitry Andric         if (error.Success())
626349cc55cSDimitry Andric           response.Printf("%zx", count);
627349cc55cSDimitry Andric         else {
628349cc55cSDimitry Andric           response.PutCString("-1");
6290b57cec5SDimitry Andric           if (save_errno)
630349cc55cSDimitry Andric             response.Printf(",%x", system_errno_to_gdb(save_errno));
631349cc55cSDimitry Andric         }
6320b57cec5SDimitry Andric       } else {
633349cc55cSDimitry Andric         response.Printf("-1,%x", EINVAL);
6340b57cec5SDimitry Andric       }
6350b57cec5SDimitry Andric       return SendPacketNoLock(response.GetString());
6360b57cec5SDimitry Andric     }
6370b57cec5SDimitry Andric   }
6380b57cec5SDimitry Andric   return SendErrorResponse(27);
6390b57cec5SDimitry Andric }
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
6420b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_Size(
6430b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
6440b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:size:"));
6450b57cec5SDimitry Andric   std::string path;
6460b57cec5SDimitry Andric   packet.GetHexByteString(path);
6470b57cec5SDimitry Andric   if (!path.empty()) {
6480b57cec5SDimitry Andric     uint64_t Size;
6490b57cec5SDimitry Andric     if (llvm::sys::fs::file_size(path, Size))
6500b57cec5SDimitry Andric       return SendErrorResponse(5);
6510b57cec5SDimitry Andric     StreamString response;
6520b57cec5SDimitry Andric     response.PutChar('F');
6530b57cec5SDimitry Andric     response.PutHex64(Size);
6540b57cec5SDimitry Andric     if (Size == UINT64_MAX) {
6550b57cec5SDimitry Andric       response.PutChar(',');
6560b57cec5SDimitry Andric       response.PutHex64(Size); // TODO: replace with Host::GetSyswideErrorCode()
6570b57cec5SDimitry Andric     }
6580b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
6590b57cec5SDimitry Andric   }
6600b57cec5SDimitry Andric   return SendErrorResponse(22);
6610b57cec5SDimitry Andric }
6620b57cec5SDimitry Andric 
6630b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
6640b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_Mode(
6650b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
6660b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:mode:"));
6670b57cec5SDimitry Andric   std::string path;
6680b57cec5SDimitry Andric   packet.GetHexByteString(path);
6690b57cec5SDimitry Andric   if (!path.empty()) {
6700b57cec5SDimitry Andric     FileSpec file_spec(path);
6710b57cec5SDimitry Andric     FileSystem::Instance().Resolve(file_spec);
6720b57cec5SDimitry Andric     std::error_code ec;
6730b57cec5SDimitry Andric     const uint32_t mode = FileSystem::Instance().GetPermissions(file_spec, ec);
6740b57cec5SDimitry Andric     StreamString response;
675349cc55cSDimitry Andric     if (mode != llvm::sys::fs::perms_not_known)
676349cc55cSDimitry Andric       response.Printf("F%x", mode);
677349cc55cSDimitry Andric     else
678349cc55cSDimitry Andric       response.Printf("F-1,%x", (int)Status(ec).GetError());
6790b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
6800b57cec5SDimitry Andric   }
6810b57cec5SDimitry Andric   return SendErrorResponse(23);
6820b57cec5SDimitry Andric }
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
6850b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_Exists(
6860b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
6870b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:exists:"));
6880b57cec5SDimitry Andric   std::string path;
6890b57cec5SDimitry Andric   packet.GetHexByteString(path);
6900b57cec5SDimitry Andric   if (!path.empty()) {
6910b57cec5SDimitry Andric     bool retcode = llvm::sys::fs::exists(path);
6920b57cec5SDimitry Andric     StreamString response;
6930b57cec5SDimitry Andric     response.PutChar('F');
6940b57cec5SDimitry Andric     response.PutChar(',');
6950b57cec5SDimitry Andric     if (retcode)
6960b57cec5SDimitry Andric       response.PutChar('1');
6970b57cec5SDimitry Andric     else
6980b57cec5SDimitry Andric       response.PutChar('0');
6990b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
7000b57cec5SDimitry Andric   }
7010b57cec5SDimitry Andric   return SendErrorResponse(24);
7020b57cec5SDimitry Andric }
7030b57cec5SDimitry Andric 
7040b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
7050b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_symlink(
7060b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
7070b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:symlink:"));
7080b57cec5SDimitry Andric   std::string dst, src;
7090b57cec5SDimitry Andric   packet.GetHexByteStringTerminatedBy(dst, ',');
7100b57cec5SDimitry Andric   packet.GetChar(); // Skip ',' char
7110b57cec5SDimitry Andric   packet.GetHexByteString(src);
7120b57cec5SDimitry Andric 
7130b57cec5SDimitry Andric   FileSpec src_spec(src);
7140b57cec5SDimitry Andric   FileSystem::Instance().Resolve(src_spec);
7150b57cec5SDimitry Andric   Status error = FileSystem::Instance().Symlink(src_spec, FileSpec(dst));
7160b57cec5SDimitry Andric 
7170b57cec5SDimitry Andric   StreamString response;
718349cc55cSDimitry Andric   response.Printf("F%x,%x", error.GetError(), error.GetError());
7190b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
7200b57cec5SDimitry Andric }
7210b57cec5SDimitry Andric 
7220b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
7230b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_unlink(
7240b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
7250b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:unlink:"));
7260b57cec5SDimitry Andric   std::string path;
7270b57cec5SDimitry Andric   packet.GetHexByteString(path);
7280b57cec5SDimitry Andric   Status error(llvm::sys::fs::remove(path));
7290b57cec5SDimitry Andric   StreamString response;
730349cc55cSDimitry Andric   response.Printf("F%x,%x", error.GetError(), error.GetError());
7310b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
7320b57cec5SDimitry Andric }
7330b57cec5SDimitry Andric 
7340b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
7350b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell(
7360b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
7370b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qPlatform_shell:"));
7380b57cec5SDimitry Andric   std::string path;
7390b57cec5SDimitry Andric   std::string working_dir;
7400b57cec5SDimitry Andric   packet.GetHexByteStringTerminatedBy(path, ',');
7410b57cec5SDimitry Andric   if (!path.empty()) {
7420b57cec5SDimitry Andric     if (packet.GetChar() == ',') {
7430b57cec5SDimitry Andric       // FIXME: add timeout to qPlatform_shell packet
7440b57cec5SDimitry Andric       // uint32_t timeout = packet.GetHexMaxU32(false, 32);
7450b57cec5SDimitry Andric       if (packet.GetChar() == ',')
7460b57cec5SDimitry Andric         packet.GetHexByteString(working_dir);
7470b57cec5SDimitry Andric       int status, signo;
7480b57cec5SDimitry Andric       std::string output;
7490b57cec5SDimitry Andric       FileSpec working_spec(working_dir);
7500b57cec5SDimitry Andric       FileSystem::Instance().Resolve(working_spec);
7510b57cec5SDimitry Andric       Status err =
7520b57cec5SDimitry Andric           Host::RunShellCommand(path.c_str(), working_spec, &status, &signo,
7530b57cec5SDimitry Andric                                 &output, std::chrono::seconds(10));
7540b57cec5SDimitry Andric       StreamGDBRemote response;
7550b57cec5SDimitry Andric       if (err.Fail()) {
7560b57cec5SDimitry Andric         response.PutCString("F,");
7570b57cec5SDimitry Andric         response.PutHex32(UINT32_MAX);
7580b57cec5SDimitry Andric       } else {
7590b57cec5SDimitry Andric         response.PutCString("F,");
7600b57cec5SDimitry Andric         response.PutHex32(status);
7610b57cec5SDimitry Andric         response.PutChar(',');
7620b57cec5SDimitry Andric         response.PutHex32(signo);
7630b57cec5SDimitry Andric         response.PutChar(',');
7640b57cec5SDimitry Andric         response.PutEscapedBytes(output.c_str(), output.size());
7650b57cec5SDimitry Andric       }
7660b57cec5SDimitry Andric       return SendPacketNoLock(response.GetString());
7670b57cec5SDimitry Andric     }
7680b57cec5SDimitry Andric   }
7690b57cec5SDimitry Andric   return SendErrorResponse(24);
7700b57cec5SDimitry Andric }
7710b57cec5SDimitry Andric 
772349cc55cSDimitry Andric template <typename T, typename U>
773349cc55cSDimitry Andric static void fill_clamp(T &dest, U src, typename T::value_type fallback) {
774349cc55cSDimitry Andric   static_assert(std::is_unsigned<typename T::value_type>::value,
775349cc55cSDimitry Andric                 "Destination type must be unsigned.");
776bdd1243dSDimitry Andric   using UU = std::make_unsigned_t<U>;
777349cc55cSDimitry Andric   constexpr auto T_max = std::numeric_limits<typename T::value_type>::max();
778349cc55cSDimitry Andric   dest = src >= 0 && static_cast<UU>(src) <= T_max ? src : fallback;
779349cc55cSDimitry Andric }
780349cc55cSDimitry Andric 
781349cc55cSDimitry Andric GDBRemoteCommunication::PacketResult
782349cc55cSDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_FStat(
783349cc55cSDimitry Andric     StringExtractorGDBRemote &packet) {
784349cc55cSDimitry Andric   StreamGDBRemote response;
785349cc55cSDimitry Andric   packet.SetFilePos(::strlen("vFile:fstat:"));
786349cc55cSDimitry Andric   int fd = packet.GetS32(-1, 16);
787349cc55cSDimitry Andric 
788349cc55cSDimitry Andric   struct stat file_stats;
789349cc55cSDimitry Andric   if (::fstat(fd, &file_stats) == -1) {
790349cc55cSDimitry Andric     const int save_errno = errno;
791349cc55cSDimitry Andric     response.Printf("F-1,%x", system_errno_to_gdb(save_errno));
792349cc55cSDimitry Andric     return SendPacketNoLock(response.GetString());
793349cc55cSDimitry Andric   }
794349cc55cSDimitry Andric 
795349cc55cSDimitry Andric   GDBRemoteFStatData data;
796349cc55cSDimitry Andric   fill_clamp(data.gdb_st_dev, file_stats.st_dev, 0);
797349cc55cSDimitry Andric   fill_clamp(data.gdb_st_ino, file_stats.st_ino, 0);
798349cc55cSDimitry Andric   data.gdb_st_mode = file_stats.st_mode;
799349cc55cSDimitry Andric   fill_clamp(data.gdb_st_nlink, file_stats.st_nlink, UINT32_MAX);
800349cc55cSDimitry Andric   fill_clamp(data.gdb_st_uid, file_stats.st_uid, 0);
801349cc55cSDimitry Andric   fill_clamp(data.gdb_st_gid, file_stats.st_gid, 0);
802349cc55cSDimitry Andric   fill_clamp(data.gdb_st_rdev, file_stats.st_rdev, 0);
803349cc55cSDimitry Andric   data.gdb_st_size = file_stats.st_size;
804349cc55cSDimitry Andric #if !defined(_WIN32)
805349cc55cSDimitry Andric   data.gdb_st_blksize = file_stats.st_blksize;
806349cc55cSDimitry Andric   data.gdb_st_blocks = file_stats.st_blocks;
807349cc55cSDimitry Andric #else
808349cc55cSDimitry Andric   data.gdb_st_blksize = 0;
809349cc55cSDimitry Andric   data.gdb_st_blocks = 0;
810349cc55cSDimitry Andric #endif
811349cc55cSDimitry Andric   fill_clamp(data.gdb_st_atime, file_stats.st_atime, 0);
812349cc55cSDimitry Andric   fill_clamp(data.gdb_st_mtime, file_stats.st_mtime, 0);
813349cc55cSDimitry Andric   fill_clamp(data.gdb_st_ctime, file_stats.st_ctime, 0);
814349cc55cSDimitry Andric 
815349cc55cSDimitry Andric   response.Printf("F%zx;", sizeof(data));
816349cc55cSDimitry Andric   response.PutEscapedBytes(&data, sizeof(data));
817349cc55cSDimitry Andric   return SendPacketNoLock(response.GetString());
818349cc55cSDimitry Andric }
819349cc55cSDimitry Andric 
8200b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
8210b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_Stat(
8220b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
8230b57cec5SDimitry Andric   return SendUnimplementedResponse(
8240b57cec5SDimitry Andric       "GDBRemoteCommunicationServerCommon::Handle_vFile_Stat() unimplemented");
8250b57cec5SDimitry Andric }
8260b57cec5SDimitry Andric 
8270b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
8280b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_MD5(
8290b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
8300b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:MD5:"));
8310b57cec5SDimitry Andric   std::string path;
8320b57cec5SDimitry Andric   packet.GetHexByteString(path);
8330b57cec5SDimitry Andric   if (!path.empty()) {
8340b57cec5SDimitry Andric     StreamGDBRemote response;
8350b57cec5SDimitry Andric     auto Result = llvm::sys::fs::md5_contents(path);
8360b57cec5SDimitry Andric     if (!Result) {
8370b57cec5SDimitry Andric       response.PutCString("F,");
8380b57cec5SDimitry Andric       response.PutCString("x");
8390b57cec5SDimitry Andric     } else {
8400b57cec5SDimitry Andric       response.PutCString("F,");
8410b57cec5SDimitry Andric       response.PutHex64(Result->low());
8420b57cec5SDimitry Andric       response.PutHex64(Result->high());
8430b57cec5SDimitry Andric     }
8440b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
8450b57cec5SDimitry Andric   }
8460b57cec5SDimitry Andric   return SendErrorResponse(25);
8470b57cec5SDimitry Andric }
8480b57cec5SDimitry Andric 
8490b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
8500b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir(
8510b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
8520b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qPlatform_mkdir:"));
8530b57cec5SDimitry Andric   mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
8540b57cec5SDimitry Andric   if (packet.GetChar() == ',') {
8550b57cec5SDimitry Andric     std::string path;
8560b57cec5SDimitry Andric     packet.GetHexByteString(path);
8570b57cec5SDimitry Andric     Status error(llvm::sys::fs::create_directory(path, mode));
8580b57cec5SDimitry Andric 
8590b57cec5SDimitry Andric     StreamGDBRemote response;
860349cc55cSDimitry Andric     response.Printf("F%x", error.GetError());
8610b57cec5SDimitry Andric 
8620b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
8630b57cec5SDimitry Andric   }
8640b57cec5SDimitry Andric   return SendErrorResponse(20);
8650b57cec5SDimitry Andric }
8660b57cec5SDimitry Andric 
8670b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
8680b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod(
8690b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
8700b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qPlatform_chmod:"));
8710b57cec5SDimitry Andric 
8720b57cec5SDimitry Andric   auto perms =
8730b57cec5SDimitry Andric       static_cast<llvm::sys::fs::perms>(packet.GetHexMaxU32(false, UINT32_MAX));
8740b57cec5SDimitry Andric   if (packet.GetChar() == ',') {
8750b57cec5SDimitry Andric     std::string path;
8760b57cec5SDimitry Andric     packet.GetHexByteString(path);
8770b57cec5SDimitry Andric     Status error(llvm::sys::fs::setPermissions(path, perms));
8780b57cec5SDimitry Andric 
8790b57cec5SDimitry Andric     StreamGDBRemote response;
880349cc55cSDimitry Andric     response.Printf("F%x", error.GetError());
8810b57cec5SDimitry Andric 
8820b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
8830b57cec5SDimitry Andric   }
8840b57cec5SDimitry Andric   return SendErrorResponse(19);
8850b57cec5SDimitry Andric }
8860b57cec5SDimitry Andric 
8870b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
8880b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qSupported(
8890b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
890fe6060f1SDimitry Andric   // Parse client-indicated features.
891fe6060f1SDimitry Andric   llvm::SmallVector<llvm::StringRef, 4> client_features;
892fe6060f1SDimitry Andric   packet.GetStringRef().split(client_features, ';');
893fe6060f1SDimitry Andric   return SendPacketNoLock(llvm::join(HandleFeatures(client_features), ";"));
8940b57cec5SDimitry Andric }
8950b57cec5SDimitry Andric 
8960b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
8970b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError(
8980b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
8990b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QSetDetachOnError:"));
9000b57cec5SDimitry Andric   if (packet.GetU32(0))
9010b57cec5SDimitry Andric     m_process_launch_info.GetFlags().Set(eLaunchFlagDetachOnError);
9020b57cec5SDimitry Andric   else
9030b57cec5SDimitry Andric     m_process_launch_info.GetFlags().Clear(eLaunchFlagDetachOnError);
9040b57cec5SDimitry Andric   return SendOKResponse();
9050b57cec5SDimitry Andric }
9060b57cec5SDimitry Andric 
9070b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
9080b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode(
9090b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
9100b57cec5SDimitry Andric   // Send response first before changing m_send_acks to we ack this packet
9110b57cec5SDimitry Andric   PacketResult packet_result = SendOKResponse();
9120b57cec5SDimitry Andric   m_send_acks = false;
9130b57cec5SDimitry Andric   return packet_result;
9140b57cec5SDimitry Andric }
9150b57cec5SDimitry Andric 
9160b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
9170b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN(
9180b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
9190b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QSetSTDIN:"));
9200b57cec5SDimitry Andric   FileAction file_action;
9210b57cec5SDimitry Andric   std::string path;
9220b57cec5SDimitry Andric   packet.GetHexByteString(path);
9230b57cec5SDimitry Andric   const bool read = true;
9240b57cec5SDimitry Andric   const bool write = false;
9250b57cec5SDimitry Andric   if (file_action.Open(STDIN_FILENO, FileSpec(path), read, write)) {
9260b57cec5SDimitry Andric     m_process_launch_info.AppendFileAction(file_action);
9270b57cec5SDimitry Andric     return SendOKResponse();
9280b57cec5SDimitry Andric   }
9290b57cec5SDimitry Andric   return SendErrorResponse(15);
9300b57cec5SDimitry Andric }
9310b57cec5SDimitry Andric 
9320b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
9330b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT(
9340b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
9350b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QSetSTDOUT:"));
9360b57cec5SDimitry Andric   FileAction file_action;
9370b57cec5SDimitry Andric   std::string path;
9380b57cec5SDimitry Andric   packet.GetHexByteString(path);
9390b57cec5SDimitry Andric   const bool read = false;
9400b57cec5SDimitry Andric   const bool write = true;
9410b57cec5SDimitry Andric   if (file_action.Open(STDOUT_FILENO, FileSpec(path), read, write)) {
9420b57cec5SDimitry Andric     m_process_launch_info.AppendFileAction(file_action);
9430b57cec5SDimitry Andric     return SendOKResponse();
9440b57cec5SDimitry Andric   }
9450b57cec5SDimitry Andric   return SendErrorResponse(16);
9460b57cec5SDimitry Andric }
9470b57cec5SDimitry Andric 
9480b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
9490b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR(
9500b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
9510b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QSetSTDERR:"));
9520b57cec5SDimitry Andric   FileAction file_action;
9530b57cec5SDimitry Andric   std::string path;
9540b57cec5SDimitry Andric   packet.GetHexByteString(path);
9550b57cec5SDimitry Andric   const bool read = false;
9560b57cec5SDimitry Andric   const bool write = true;
9570b57cec5SDimitry Andric   if (file_action.Open(STDERR_FILENO, FileSpec(path), read, write)) {
9580b57cec5SDimitry Andric     m_process_launch_info.AppendFileAction(file_action);
9590b57cec5SDimitry Andric     return SendOKResponse();
9600b57cec5SDimitry Andric   }
9610b57cec5SDimitry Andric   return SendErrorResponse(17);
9620b57cec5SDimitry Andric }
9630b57cec5SDimitry Andric 
9640b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
9650b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess(
9660b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
9670b57cec5SDimitry Andric   if (m_process_launch_error.Success())
9680b57cec5SDimitry Andric     return SendOKResponse();
9690b57cec5SDimitry Andric   StreamString response;
9700b57cec5SDimitry Andric   response.PutChar('E');
9710b57cec5SDimitry Andric   response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
9720b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
9730b57cec5SDimitry Andric }
9740b57cec5SDimitry Andric 
9750b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
9760b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QEnvironment(
9770b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
9780b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QEnvironment:"));
9790b57cec5SDimitry Andric   const uint32_t bytes_left = packet.GetBytesLeft();
9800b57cec5SDimitry Andric   if (bytes_left > 0) {
9810b57cec5SDimitry Andric     m_process_launch_info.GetEnvironment().insert(packet.Peek());
9820b57cec5SDimitry Andric     return SendOKResponse();
9830b57cec5SDimitry Andric   }
9840b57cec5SDimitry Andric   return SendErrorResponse(12);
9850b57cec5SDimitry Andric }
9860b57cec5SDimitry Andric 
9870b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
9880b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded(
9890b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
9900b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QEnvironmentHexEncoded:"));
9910b57cec5SDimitry Andric   const uint32_t bytes_left = packet.GetBytesLeft();
9920b57cec5SDimitry Andric   if (bytes_left > 0) {
9930b57cec5SDimitry Andric     std::string str;
9940b57cec5SDimitry Andric     packet.GetHexByteString(str);
9950b57cec5SDimitry Andric     m_process_launch_info.GetEnvironment().insert(str);
9960b57cec5SDimitry Andric     return SendOKResponse();
9970b57cec5SDimitry Andric   }
9980b57cec5SDimitry Andric   return SendErrorResponse(12);
9990b57cec5SDimitry Andric }
10000b57cec5SDimitry Andric 
10010b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
10020b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QLaunchArch(
10030b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
10040b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QLaunchArch:"));
10050b57cec5SDimitry Andric   const uint32_t bytes_left = packet.GetBytesLeft();
10060b57cec5SDimitry Andric   if (bytes_left > 0) {
10070b57cec5SDimitry Andric     const char *arch_triple = packet.Peek();
10080b57cec5SDimitry Andric     m_process_launch_info.SetArchitecture(
10090b57cec5SDimitry Andric         HostInfo::GetAugmentedArchSpec(arch_triple));
10100b57cec5SDimitry Andric     return SendOKResponse();
10110b57cec5SDimitry Andric   }
10120b57cec5SDimitry Andric   return SendErrorResponse(13);
10130b57cec5SDimitry Andric }
10140b57cec5SDimitry Andric 
10150b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
10160b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
10170b57cec5SDimitry Andric   // The 'A' packet is the most over designed packet ever here with redundant
10180b57cec5SDimitry Andric   // argument indexes, redundant argument lengths and needed hex encoded
10190b57cec5SDimitry Andric   // argument string values. Really all that is needed is a comma separated hex
10200b57cec5SDimitry Andric   // encoded argument value list, but we will stay true to the documented
10210b57cec5SDimitry Andric   // version of the 'A' packet here...
10220b57cec5SDimitry Andric 
102381ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
10240b57cec5SDimitry Andric   int actual_arg_index = 0;
10250b57cec5SDimitry Andric 
10260b57cec5SDimitry Andric   packet.SetFilePos(1); // Skip the 'A'
10270b57cec5SDimitry Andric   bool success = true;
10280b57cec5SDimitry Andric   while (success && packet.GetBytesLeft() > 0) {
10290b57cec5SDimitry Andric     // Decode the decimal argument string length. This length is the number of
10300b57cec5SDimitry Andric     // hex nibbles in the argument string value.
10310b57cec5SDimitry Andric     const uint32_t arg_len = packet.GetU32(UINT32_MAX);
10320b57cec5SDimitry Andric     if (arg_len == UINT32_MAX)
10330b57cec5SDimitry Andric       success = false;
10340b57cec5SDimitry Andric     else {
10350b57cec5SDimitry Andric       // Make sure the argument hex string length is followed by a comma
10360b57cec5SDimitry Andric       if (packet.GetChar() != ',')
10370b57cec5SDimitry Andric         success = false;
10380b57cec5SDimitry Andric       else {
10390b57cec5SDimitry Andric         // Decode the argument index. We ignore this really because who would
10400b57cec5SDimitry Andric         // really send down the arguments in a random order???
10410b57cec5SDimitry Andric         const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
10420b57cec5SDimitry Andric         if (arg_idx == UINT32_MAX)
10430b57cec5SDimitry Andric           success = false;
10440b57cec5SDimitry Andric         else {
10450b57cec5SDimitry Andric           // Make sure the argument index is followed by a comma
10460b57cec5SDimitry Andric           if (packet.GetChar() != ',')
10470b57cec5SDimitry Andric             success = false;
10480b57cec5SDimitry Andric           else {
10490b57cec5SDimitry Andric             // Decode the argument string value from hex bytes back into a UTF8
10500b57cec5SDimitry Andric             // string and make sure the length matches the one supplied in the
10510b57cec5SDimitry Andric             // packet
10520b57cec5SDimitry Andric             std::string arg;
10530b57cec5SDimitry Andric             if (packet.GetHexByteStringFixedLength(arg, arg_len) !=
10540b57cec5SDimitry Andric                 (arg_len / 2))
10550b57cec5SDimitry Andric               success = false;
10560b57cec5SDimitry Andric             else {
10570b57cec5SDimitry Andric               // If there are any bytes left
10580b57cec5SDimitry Andric               if (packet.GetBytesLeft()) {
10590b57cec5SDimitry Andric                 if (packet.GetChar() != ',')
10600b57cec5SDimitry Andric                   success = false;
10610b57cec5SDimitry Andric               }
10620b57cec5SDimitry Andric 
10630b57cec5SDimitry Andric               if (success) {
10640b57cec5SDimitry Andric                 if (arg_idx == 0)
10650b57cec5SDimitry Andric                   m_process_launch_info.GetExecutableFile().SetFile(
10660b57cec5SDimitry Andric                       arg, FileSpec::Style::native);
10670b57cec5SDimitry Andric                 m_process_launch_info.GetArguments().AppendArgument(arg);
10689dba64beSDimitry Andric                 LLDB_LOGF(log, "LLGSPacketHandler::%s added arg %d: \"%s\"",
10690b57cec5SDimitry Andric                           __FUNCTION__, actual_arg_index, arg.c_str());
10700b57cec5SDimitry Andric                 ++actual_arg_index;
10710b57cec5SDimitry Andric               }
10720b57cec5SDimitry Andric             }
10730b57cec5SDimitry Andric           }
10740b57cec5SDimitry Andric         }
10750b57cec5SDimitry Andric       }
10760b57cec5SDimitry Andric     }
10770b57cec5SDimitry Andric   }
10780b57cec5SDimitry Andric 
10790b57cec5SDimitry Andric   if (success) {
10800b57cec5SDimitry Andric     m_process_launch_error = LaunchProcess();
10810b57cec5SDimitry Andric     if (m_process_launch_error.Success())
10820b57cec5SDimitry Andric       return SendOKResponse();
10830b57cec5SDimitry Andric     LLDB_LOG(log, "failed to launch exe: {0}", m_process_launch_error);
10840b57cec5SDimitry Andric   }
10850b57cec5SDimitry Andric   return SendErrorResponse(8);
10860b57cec5SDimitry Andric }
10870b57cec5SDimitry Andric 
10880b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
10890b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qEcho(
10900b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
10910b57cec5SDimitry Andric   // Just echo back the exact same packet for qEcho...
10920b57cec5SDimitry Andric   return SendPacketNoLock(packet.GetStringRef());
10930b57cec5SDimitry Andric }
10940b57cec5SDimitry Andric 
10950b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
10960b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qModuleInfo(
10970b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
10980b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qModuleInfo:"));
10990b57cec5SDimitry Andric 
11000b57cec5SDimitry Andric   std::string module_path;
11010b57cec5SDimitry Andric   packet.GetHexByteStringTerminatedBy(module_path, ';');
11020b57cec5SDimitry Andric   if (module_path.empty())
11030b57cec5SDimitry Andric     return SendErrorResponse(1);
11040b57cec5SDimitry Andric 
11050b57cec5SDimitry Andric   if (packet.GetChar() != ';')
11060b57cec5SDimitry Andric     return SendErrorResponse(2);
11070b57cec5SDimitry Andric 
11080b57cec5SDimitry Andric   std::string triple;
11090b57cec5SDimitry Andric   packet.GetHexByteString(triple);
11100b57cec5SDimitry Andric 
11110b57cec5SDimitry Andric   ModuleSpec matched_module_spec = GetModuleInfo(module_path, triple);
11120b57cec5SDimitry Andric   if (!matched_module_spec.GetFileSpec())
11130b57cec5SDimitry Andric     return SendErrorResponse(3);
11140b57cec5SDimitry Andric 
11150b57cec5SDimitry Andric   const auto file_offset = matched_module_spec.GetObjectOffset();
11160b57cec5SDimitry Andric   const auto file_size = matched_module_spec.GetObjectSize();
11170b57cec5SDimitry Andric   const auto uuid_str = matched_module_spec.GetUUID().GetAsString("");
11180b57cec5SDimitry Andric 
11190b57cec5SDimitry Andric   StreamGDBRemote response;
11200b57cec5SDimitry Andric 
11210b57cec5SDimitry Andric   if (uuid_str.empty()) {
11220b57cec5SDimitry Andric     auto Result = llvm::sys::fs::md5_contents(
11230b57cec5SDimitry Andric         matched_module_spec.GetFileSpec().GetPath());
11240b57cec5SDimitry Andric     if (!Result)
11250b57cec5SDimitry Andric       return SendErrorResponse(5);
11260b57cec5SDimitry Andric     response.PutCString("md5:");
11270b57cec5SDimitry Andric     response.PutStringAsRawHex8(Result->digest());
11280b57cec5SDimitry Andric   } else {
11290b57cec5SDimitry Andric     response.PutCString("uuid:");
11300b57cec5SDimitry Andric     response.PutStringAsRawHex8(uuid_str);
11310b57cec5SDimitry Andric   }
11320b57cec5SDimitry Andric   response.PutChar(';');
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric   const auto &module_arch = matched_module_spec.GetArchitecture();
11350b57cec5SDimitry Andric   response.PutCString("triple:");
11360b57cec5SDimitry Andric   response.PutStringAsRawHex8(module_arch.GetTriple().getTriple());
11370b57cec5SDimitry Andric   response.PutChar(';');
11380b57cec5SDimitry Andric 
11390b57cec5SDimitry Andric   response.PutCString("file_path:");
1140bdd1243dSDimitry Andric   response.PutStringAsRawHex8(
1141bdd1243dSDimitry Andric       matched_module_spec.GetFileSpec().GetPath().c_str());
11420b57cec5SDimitry Andric   response.PutChar(';');
11430b57cec5SDimitry Andric   response.PutCString("file_offset:");
11440b57cec5SDimitry Andric   response.PutHex64(file_offset);
11450b57cec5SDimitry Andric   response.PutChar(';');
11460b57cec5SDimitry Andric   response.PutCString("file_size:");
11470b57cec5SDimitry Andric   response.PutHex64(file_size);
11480b57cec5SDimitry Andric   response.PutChar(';');
11490b57cec5SDimitry Andric 
11500b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
11510b57cec5SDimitry Andric }
11520b57cec5SDimitry Andric 
11530b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
11540b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_jModulesInfo(
11550b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
11569dba64beSDimitry Andric   namespace json = llvm::json;
11579dba64beSDimitry Andric 
11580b57cec5SDimitry Andric   packet.SetFilePos(::strlen("jModulesInfo:"));
11590b57cec5SDimitry Andric 
11600b57cec5SDimitry Andric   StructuredData::ObjectSP object_sp = StructuredData::ParseJSON(packet.Peek());
11610b57cec5SDimitry Andric   if (!object_sp)
11620b57cec5SDimitry Andric     return SendErrorResponse(1);
11630b57cec5SDimitry Andric 
11640b57cec5SDimitry Andric   StructuredData::Array *packet_array = object_sp->GetAsArray();
11650b57cec5SDimitry Andric   if (!packet_array)
11660b57cec5SDimitry Andric     return SendErrorResponse(2);
11670b57cec5SDimitry Andric 
11689dba64beSDimitry Andric   json::Array response_array;
11690b57cec5SDimitry Andric   for (size_t i = 0; i < packet_array->GetSize(); ++i) {
11700b57cec5SDimitry Andric     StructuredData::Dictionary *query =
11710b57cec5SDimitry Andric         packet_array->GetItemAtIndex(i)->GetAsDictionary();
11720b57cec5SDimitry Andric     if (!query)
11730b57cec5SDimitry Andric       continue;
11740b57cec5SDimitry Andric     llvm::StringRef file, triple;
11750b57cec5SDimitry Andric     if (!query->GetValueForKeyAsString("file", file) ||
11760b57cec5SDimitry Andric         !query->GetValueForKeyAsString("triple", triple))
11770b57cec5SDimitry Andric       continue;
11780b57cec5SDimitry Andric 
11790b57cec5SDimitry Andric     ModuleSpec matched_module_spec = GetModuleInfo(file, triple);
11800b57cec5SDimitry Andric     if (!matched_module_spec.GetFileSpec())
11810b57cec5SDimitry Andric       continue;
11820b57cec5SDimitry Andric 
11830b57cec5SDimitry Andric     const auto file_offset = matched_module_spec.GetObjectOffset();
11840b57cec5SDimitry Andric     const auto file_size = matched_module_spec.GetObjectSize();
11850b57cec5SDimitry Andric     const auto uuid_str = matched_module_spec.GetUUID().GetAsString("");
11860b57cec5SDimitry Andric     if (uuid_str.empty())
11870b57cec5SDimitry Andric       continue;
11889dba64beSDimitry Andric     const auto triple_str =
11899dba64beSDimitry Andric         matched_module_spec.GetArchitecture().GetTriple().getTriple();
11909dba64beSDimitry Andric     const auto file_path = matched_module_spec.GetFileSpec().GetPath();
11910b57cec5SDimitry Andric 
11929dba64beSDimitry Andric     json::Object response{{"uuid", uuid_str},
11939dba64beSDimitry Andric                           {"triple", triple_str},
11949dba64beSDimitry Andric                           {"file_path", file_path},
11959dba64beSDimitry Andric                           {"file_offset", static_cast<int64_t>(file_offset)},
11969dba64beSDimitry Andric                           {"file_size", static_cast<int64_t>(file_size)}};
11979dba64beSDimitry Andric     response_array.push_back(std::move(response));
11980b57cec5SDimitry Andric   }
11990b57cec5SDimitry Andric 
12000b57cec5SDimitry Andric   StreamString response;
12019dba64beSDimitry Andric   response.AsRawOstream() << std::move(response_array);
12020b57cec5SDimitry Andric   StreamGDBRemote escaped_response;
12030b57cec5SDimitry Andric   escaped_response.PutEscapedBytes(response.GetString().data(),
12040b57cec5SDimitry Andric                                    response.GetSize());
12050b57cec5SDimitry Andric   return SendPacketNoLock(escaped_response.GetString());
12060b57cec5SDimitry Andric }
12070b57cec5SDimitry Andric 
12080b57cec5SDimitry Andric void GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse(
12090b57cec5SDimitry Andric     const ProcessInstanceInfo &proc_info, StreamString &response) {
12100b57cec5SDimitry Andric   response.Printf(
12110b57cec5SDimitry Andric       "pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;",
12120b57cec5SDimitry Andric       proc_info.GetProcessID(), proc_info.GetParentProcessID(),
12130b57cec5SDimitry Andric       proc_info.GetUserID(), proc_info.GetGroupID(),
12140b57cec5SDimitry Andric       proc_info.GetEffectiveUserID(), proc_info.GetEffectiveGroupID());
12150b57cec5SDimitry Andric   response.PutCString("name:");
1216bdd1243dSDimitry Andric   response.PutStringAsRawHex8(proc_info.GetExecutableFile().GetPath().c_str());
12179dba64beSDimitry Andric 
12189dba64beSDimitry Andric   response.PutChar(';');
12199dba64beSDimitry Andric   response.PutCString("args:");
12209dba64beSDimitry Andric   response.PutStringAsRawHex8(proc_info.GetArg0());
12219dba64beSDimitry Andric   for (auto &arg : proc_info.GetArguments()) {
12229dba64beSDimitry Andric     response.PutChar('-');
12239dba64beSDimitry Andric     response.PutStringAsRawHex8(arg.ref());
12249dba64beSDimitry Andric   }
12259dba64beSDimitry Andric 
12260b57cec5SDimitry Andric   response.PutChar(';');
12270b57cec5SDimitry Andric   const ArchSpec &proc_arch = proc_info.GetArchitecture();
12280b57cec5SDimitry Andric   if (proc_arch.IsValid()) {
12290b57cec5SDimitry Andric     const llvm::Triple &proc_triple = proc_arch.GetTriple();
12300b57cec5SDimitry Andric     response.PutCString("triple:");
12310b57cec5SDimitry Andric     response.PutStringAsRawHex8(proc_triple.getTriple());
12320b57cec5SDimitry Andric     response.PutChar(';');
12330b57cec5SDimitry Andric   }
12340b57cec5SDimitry Andric }
12350b57cec5SDimitry Andric 
12360b57cec5SDimitry Andric void GDBRemoteCommunicationServerCommon::
12370b57cec5SDimitry Andric     CreateProcessInfoResponse_DebugServerStyle(
12380b57cec5SDimitry Andric         const ProcessInstanceInfo &proc_info, StreamString &response) {
12390b57cec5SDimitry Andric   response.Printf("pid:%" PRIx64 ";parent-pid:%" PRIx64
12400b57cec5SDimitry Andric                   ";real-uid:%x;real-gid:%x;effective-uid:%x;effective-gid:%x;",
12410b57cec5SDimitry Andric                   proc_info.GetProcessID(), proc_info.GetParentProcessID(),
12420b57cec5SDimitry Andric                   proc_info.GetUserID(), proc_info.GetGroupID(),
12430b57cec5SDimitry Andric                   proc_info.GetEffectiveUserID(),
12440b57cec5SDimitry Andric                   proc_info.GetEffectiveGroupID());
12450b57cec5SDimitry Andric 
12460b57cec5SDimitry Andric   const ArchSpec &proc_arch = proc_info.GetArchitecture();
12470b57cec5SDimitry Andric   if (proc_arch.IsValid()) {
12480b57cec5SDimitry Andric     const llvm::Triple &proc_triple = proc_arch.GetTriple();
12490b57cec5SDimitry Andric #if defined(__APPLE__)
12500b57cec5SDimitry Andric     // We'll send cputype/cpusubtype.
12510b57cec5SDimitry Andric     const uint32_t cpu_type = proc_arch.GetMachOCPUType();
12520b57cec5SDimitry Andric     if (cpu_type != 0)
12530b57cec5SDimitry Andric       response.Printf("cputype:%" PRIx32 ";", cpu_type);
12540b57cec5SDimitry Andric 
12550b57cec5SDimitry Andric     const uint32_t cpu_subtype = proc_arch.GetMachOCPUSubType();
12560b57cec5SDimitry Andric     if (cpu_subtype != 0)
12570b57cec5SDimitry Andric       response.Printf("cpusubtype:%" PRIx32 ";", cpu_subtype);
12580b57cec5SDimitry Andric 
12595ffd83dbSDimitry Andric     const std::string vendor = proc_triple.getVendorName().str();
12600b57cec5SDimitry Andric     if (!vendor.empty())
12610b57cec5SDimitry Andric       response.Printf("vendor:%s;", vendor.c_str());
12620b57cec5SDimitry Andric #else
12630b57cec5SDimitry Andric     // We'll send the triple.
12640b57cec5SDimitry Andric     response.PutCString("triple:");
12650b57cec5SDimitry Andric     response.PutStringAsRawHex8(proc_triple.getTriple());
12660b57cec5SDimitry Andric     response.PutChar(';');
12670b57cec5SDimitry Andric #endif
12685ffd83dbSDimitry Andric     std::string ostype = std::string(proc_triple.getOSName());
12690b57cec5SDimitry Andric     // Adjust so ostype reports ios for Apple/ARM and Apple/ARM64.
12700b57cec5SDimitry Andric     if (proc_triple.getVendor() == llvm::Triple::Apple) {
12710b57cec5SDimitry Andric       switch (proc_triple.getArch()) {
12720b57cec5SDimitry Andric       case llvm::Triple::arm:
12730b57cec5SDimitry Andric       case llvm::Triple::thumb:
12740b57cec5SDimitry Andric       case llvm::Triple::aarch64:
12759dba64beSDimitry Andric       case llvm::Triple::aarch64_32:
12760b57cec5SDimitry Andric         ostype = "ios";
12770b57cec5SDimitry Andric         break;
12780b57cec5SDimitry Andric       default:
12790b57cec5SDimitry Andric         // No change.
12800b57cec5SDimitry Andric         break;
12810b57cec5SDimitry Andric       }
12820b57cec5SDimitry Andric     }
12830b57cec5SDimitry Andric     response.Printf("ostype:%s;", ostype.c_str());
12840b57cec5SDimitry Andric 
12850b57cec5SDimitry Andric     switch (proc_arch.GetByteOrder()) {
12860b57cec5SDimitry Andric     case lldb::eByteOrderLittle:
12870b57cec5SDimitry Andric       response.PutCString("endian:little;");
12880b57cec5SDimitry Andric       break;
12890b57cec5SDimitry Andric     case lldb::eByteOrderBig:
12900b57cec5SDimitry Andric       response.PutCString("endian:big;");
12910b57cec5SDimitry Andric       break;
12920b57cec5SDimitry Andric     case lldb::eByteOrderPDP:
12930b57cec5SDimitry Andric       response.PutCString("endian:pdp;");
12940b57cec5SDimitry Andric       break;
12950b57cec5SDimitry Andric     default:
12960b57cec5SDimitry Andric       // Nothing.
12970b57cec5SDimitry Andric       break;
12980b57cec5SDimitry Andric     }
12990b57cec5SDimitry Andric     // In case of MIPS64, pointer size is depend on ELF ABI For N32 the pointer
13000b57cec5SDimitry Andric     // size is 4 and for N64 it is 8
13010b57cec5SDimitry Andric     std::string abi = proc_arch.GetTargetABI();
13020b57cec5SDimitry Andric     if (!abi.empty())
13030b57cec5SDimitry Andric       response.Printf("elf_abi:%s;", abi.c_str());
13040b57cec5SDimitry Andric     response.Printf("ptrsize:%d;", proc_arch.GetAddressByteSize());
13050b57cec5SDimitry Andric   }
13060b57cec5SDimitry Andric }
13070b57cec5SDimitry Andric 
13080b57cec5SDimitry Andric FileSpec GDBRemoteCommunicationServerCommon::FindModuleFile(
13090b57cec5SDimitry Andric     const std::string &module_path, const ArchSpec &arch) {
13100b57cec5SDimitry Andric #ifdef __ANDROID__
13110b57cec5SDimitry Andric   return HostInfoAndroid::ResolveLibraryPath(module_path, arch);
13120b57cec5SDimitry Andric #else
13130b57cec5SDimitry Andric   FileSpec file_spec(module_path);
13140b57cec5SDimitry Andric   FileSystem::Instance().Resolve(file_spec);
13150b57cec5SDimitry Andric   return file_spec;
13160b57cec5SDimitry Andric #endif
13170b57cec5SDimitry Andric }
13180b57cec5SDimitry Andric 
13190b57cec5SDimitry Andric ModuleSpec
13200b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::GetModuleInfo(llvm::StringRef module_path,
13210b57cec5SDimitry Andric                                                   llvm::StringRef triple) {
13220b57cec5SDimitry Andric   ArchSpec arch(triple);
13230b57cec5SDimitry Andric 
13240b57cec5SDimitry Andric   FileSpec req_module_path_spec(module_path);
13250b57cec5SDimitry Andric   FileSystem::Instance().Resolve(req_module_path_spec);
13260b57cec5SDimitry Andric 
13270b57cec5SDimitry Andric   const FileSpec module_path_spec =
13280b57cec5SDimitry Andric       FindModuleFile(req_module_path_spec.GetPath(), arch);
132906c3fb27SDimitry Andric 
133006c3fb27SDimitry Andric   lldb::offset_t file_offset = 0;
133106c3fb27SDimitry Andric   lldb::offset_t file_size = 0;
133206c3fb27SDimitry Andric #ifdef __ANDROID__
133306c3fb27SDimitry Andric   // In Android API level 23 and above, dynamic loader is able to load .so file
133406c3fb27SDimitry Andric   // directly from zip file. In that case, module_path will be
133506c3fb27SDimitry Andric   // "zip_path!/so_path". Resolve the zip file path, .so file offset and size.
133606c3fb27SDimitry Andric   ZipFileResolver::FileKind file_kind = ZipFileResolver::eFileKindInvalid;
133706c3fb27SDimitry Andric   std::string file_path;
133806c3fb27SDimitry Andric   if (!ZipFileResolver::ResolveSharedLibraryPath(
133906c3fb27SDimitry Andric           module_path_spec, file_kind, file_path, file_offset, file_size)) {
134006c3fb27SDimitry Andric     return ModuleSpec();
134106c3fb27SDimitry Andric   }
134206c3fb27SDimitry Andric   lldbassert(file_kind != ZipFileResolver::eFileKindInvalid);
134306c3fb27SDimitry Andric   // For zip .so file, this file_path will contain only the actual zip file
134406c3fb27SDimitry Andric   // path for the object file processing. Otherwise it is the same as
134506c3fb27SDimitry Andric   // module_path.
134606c3fb27SDimitry Andric   const FileSpec actual_module_path_spec(file_path);
134706c3fb27SDimitry Andric #else
134806c3fb27SDimitry Andric   // It is just module_path_spec reference for other platforms.
134906c3fb27SDimitry Andric   const FileSpec &actual_module_path_spec = module_path_spec;
135006c3fb27SDimitry Andric #endif
135106c3fb27SDimitry Andric 
135206c3fb27SDimitry Andric   const ModuleSpec module_spec(actual_module_path_spec, arch);
13530b57cec5SDimitry Andric 
13540b57cec5SDimitry Andric   ModuleSpecList module_specs;
135506c3fb27SDimitry Andric   if (!ObjectFile::GetModuleSpecifications(actual_module_path_spec, file_offset,
135606c3fb27SDimitry Andric                                            file_size, module_specs))
13570b57cec5SDimitry Andric     return ModuleSpec();
13580b57cec5SDimitry Andric 
13590b57cec5SDimitry Andric   ModuleSpec matched_module_spec;
13600b57cec5SDimitry Andric   if (!module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec))
13610b57cec5SDimitry Andric     return ModuleSpec();
13620b57cec5SDimitry Andric 
136306c3fb27SDimitry Andric #ifdef __ANDROID__
136406c3fb27SDimitry Andric   if (file_kind == ZipFileResolver::eFileKindZip) {
136506c3fb27SDimitry Andric     // For zip .so file, matched_module_spec contains only the actual zip file
136606c3fb27SDimitry Andric     // path for the object file processing. Overwrite the matched_module_spec
136706c3fb27SDimitry Andric     // file spec with the original module_path_spec to pass "zip_path!/so_path"
136806c3fb27SDimitry Andric     // through to PlatformAndroid::DownloadModuleSlice.
136906c3fb27SDimitry Andric     *matched_module_spec.GetFileSpecPtr() = module_path_spec;
137006c3fb27SDimitry Andric   }
137106c3fb27SDimitry Andric #endif
137206c3fb27SDimitry Andric 
13730b57cec5SDimitry Andric   return matched_module_spec;
13740b57cec5SDimitry Andric }
1375fe6060f1SDimitry Andric 
1376fe6060f1SDimitry Andric std::vector<std::string> GDBRemoteCommunicationServerCommon::HandleFeatures(
1377fe6060f1SDimitry Andric     const llvm::ArrayRef<llvm::StringRef> client_features) {
1378fe6060f1SDimitry Andric   // 128KBytes is a reasonable max packet size--debugger can always use less.
1379fe6060f1SDimitry Andric   constexpr uint32_t max_packet_size = 128 * 1024;
1380fe6060f1SDimitry Andric 
1381fe6060f1SDimitry Andric   // Features common to platform server and llgs.
1382fe6060f1SDimitry Andric   return {
1383fe6060f1SDimitry Andric       llvm::formatv("PacketSize={0}", max_packet_size),
1384fe6060f1SDimitry Andric       "QStartNoAckMode+",
1385fe6060f1SDimitry Andric       "qEcho+",
1386349cc55cSDimitry Andric       "native-signals+",
1387fe6060f1SDimitry Andric   };
1388fe6060f1SDimitry Andric }
1389