10b57cec5SDimitry Andric //===-- GDBRemoteCommunicationServerCommon.cpp ------------------*- C++ -*-===//
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 
110b57cec5SDimitry Andric #include <errno.h>
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifdef __APPLE__
140b57cec5SDimitry Andric #include <TargetConditionals.h>
150b57cec5SDimitry Andric #endif
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include <chrono>
180b57cec5SDimitry Andric #include <cstring>
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric #include "lldb/Core/ModuleSpec.h"
210b57cec5SDimitry Andric #include "lldb/Host/Config.h"
220b57cec5SDimitry Andric #include "lldb/Host/File.h"
230b57cec5SDimitry Andric #include "lldb/Host/FileAction.h"
240b57cec5SDimitry Andric #include "lldb/Host/FileSystem.h"
250b57cec5SDimitry Andric #include "lldb/Host/Host.h"
260b57cec5SDimitry Andric #include "lldb/Host/HostInfo.h"
270b57cec5SDimitry Andric #include "lldb/Host/SafeMachO.h"
280b57cec5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h"
290b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h"
300b57cec5SDimitry Andric #include "lldb/Target/Platform.h"
310b57cec5SDimitry Andric #include "lldb/Utility/Endian.h"
32*9dba64beSDimitry Andric #include "lldb/Utility/GDBRemote.h"
330b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
340b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
350b57cec5SDimitry Andric #include "lldb/Utility/StructuredData.h"
36*9dba64beSDimitry Andric #include "llvm/ADT/StringSwitch.h"
370b57cec5SDimitry Andric #include "llvm/ADT/Triple.h"
38*9dba64beSDimitry Andric #include "llvm/Support/JSON.h"
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric #include "ProcessGDBRemoteLog.h"
410b57cec5SDimitry Andric #include "lldb/Utility/StringExtractorGDBRemote.h"
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric #ifdef __ANDROID__
440b57cec5SDimitry Andric #include "lldb/Host/android/HostInfoAndroid.h"
450b57cec5SDimitry Andric #endif
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric using namespace lldb;
490b57cec5SDimitry Andric using namespace lldb_private::process_gdb_remote;
50*9dba64beSDimitry Andric using namespace lldb_private;
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric #ifdef __ANDROID__
530b57cec5SDimitry Andric const static uint32_t g_default_packet_timeout_sec = 20; // seconds
540b57cec5SDimitry Andric #else
550b57cec5SDimitry Andric const static uint32_t g_default_packet_timeout_sec = 0; // not specified
560b57cec5SDimitry Andric #endif
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric // GDBRemoteCommunicationServerCommon constructor
590b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon(
600b57cec5SDimitry Andric     const char *comm_name, const char *listener_name)
610b57cec5SDimitry Andric     : GDBRemoteCommunicationServer(comm_name, listener_name),
620b57cec5SDimitry Andric       m_process_launch_info(), m_process_launch_error(), m_proc_infos(),
630b57cec5SDimitry Andric       m_proc_infos_index(0), m_thread_suffix_supported(false),
640b57cec5SDimitry Andric       m_list_threads_in_stop_reply(false) {
650b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_A,
660b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerCommon::Handle_A);
670b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
680b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QEnvironment,
690b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_QEnvironment);
700b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
710b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QEnvironmentHexEncoded,
720b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded);
730b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
740b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qfProcessInfo,
750b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo);
760b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
770b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qGroupName,
780b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qGroupName);
790b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
800b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qHostInfo,
810b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qHostInfo);
820b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
830b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QLaunchArch,
840b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_QLaunchArch);
850b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
860b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess,
870b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess);
880b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
890b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply,
900b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply);
910b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
920b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qEcho,
930b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qEcho);
940b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
950b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qModuleInfo,
960b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qModuleInfo);
970b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
980b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_jModulesInfo,
990b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_jModulesInfo);
1000b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1010b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod,
1020b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod);
1030b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1040b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir,
1050b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir);
1060b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1070b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qPlatform_shell,
1080b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell);
1090b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1100b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID,
1110b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qProcessInfoPID);
1120b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1130b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QSetDetachOnError,
1140b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError);
1150b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1160b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QSetSTDERR,
1170b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR);
1180b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1190b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QSetSTDIN,
1200b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN);
1210b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1220b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT,
1230b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT);
1240b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1250b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qSpeedTest,
1260b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qSpeedTest);
1270b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1280b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qsProcessInfo,
1290b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo);
1300b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1310b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode,
1320b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode);
1330b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1340b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qSupported,
1350b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qSupported);
1360b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1370b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported,
1380b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported);
1390b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1400b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qUserName,
1410b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_qUserName);
1420b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1430b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_close,
1440b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_Close);
1450b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1460b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_exists,
1470b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_Exists);
1480b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1490b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_md5,
1500b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_MD5);
1510b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1520b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_mode,
1530b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_Mode);
1540b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1550b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_open,
1560b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_Open);
1570b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1580b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_pread,
1590b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_pRead);
1600b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1610b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_pwrite,
1620b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite);
1630b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1640b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_size,
1650b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_Size);
1660b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1670b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_stat,
1680b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_Stat);
1690b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1700b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_symlink,
1710b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_symlink);
1720b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1730b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vFile_unlink,
1740b57cec5SDimitry Andric       &GDBRemoteCommunicationServerCommon::Handle_vFile_unlink);
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric // Destructor
1780b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::~GDBRemoteCommunicationServerCommon() {}
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
1810b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qHostInfo(
1820b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
1830b57cec5SDimitry Andric   StreamString response;
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric   // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   ArchSpec host_arch(HostInfo::GetArchitecture());
1880b57cec5SDimitry Andric   const llvm::Triple &host_triple = host_arch.GetTriple();
1890b57cec5SDimitry Andric   response.PutCString("triple:");
1900b57cec5SDimitry Andric   response.PutStringAsRawHex8(host_triple.getTriple());
1910b57cec5SDimitry Andric   response.Printf(";ptrsize:%u;", host_arch.GetAddressByteSize());
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   const char *distribution_id = host_arch.GetDistributionId().AsCString();
1940b57cec5SDimitry Andric   if (distribution_id) {
1950b57cec5SDimitry Andric     response.PutCString("distribution_id:");
1960b57cec5SDimitry Andric     response.PutStringAsRawHex8(distribution_id);
1970b57cec5SDimitry Andric     response.PutCString(";");
1980b57cec5SDimitry Andric   }
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric #if defined(__APPLE__)
2010b57cec5SDimitry Andric   // For parity with debugserver, we'll include the vendor key.
2020b57cec5SDimitry Andric   response.PutCString("vendor:apple;");
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric   // Send out MachO info.
2050b57cec5SDimitry Andric   uint32_t cpu = host_arch.GetMachOCPUType();
2060b57cec5SDimitry Andric   uint32_t sub = host_arch.GetMachOCPUSubType();
2070b57cec5SDimitry Andric   if (cpu != LLDB_INVALID_CPUTYPE)
2080b57cec5SDimitry Andric     response.Printf("cputype:%u;", cpu);
2090b57cec5SDimitry Andric   if (sub != LLDB_INVALID_CPUTYPE)
2100b57cec5SDimitry Andric     response.Printf("cpusubtype:%u;", sub);
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   if (cpu == llvm::MachO::CPU_TYPE_ARM || cpu == llvm::MachO::CPU_TYPE_ARM64) {
2130b57cec5SDimitry Andric // Indicate the OS type.
2140b57cec5SDimitry Andric #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
2150b57cec5SDimitry Andric     response.PutCString("ostype:tvos;");
2160b57cec5SDimitry Andric #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
2170b57cec5SDimitry Andric     response.PutCString("ostype:watchos;");
2180b57cec5SDimitry Andric #elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
2190b57cec5SDimitry Andric     response.PutCString("ostype:bridgeos;");
2200b57cec5SDimitry Andric #else
2210b57cec5SDimitry Andric     response.PutCString("ostype:ios;");
2220b57cec5SDimitry Andric #endif
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric     // On arm, we use "synchronous" watchpoints which means the exception is
2250b57cec5SDimitry Andric     // delivered before the instruction executes.
2260b57cec5SDimitry Andric     response.PutCString("watchpoint_exceptions_received:before;");
2270b57cec5SDimitry Andric   } else {
2280b57cec5SDimitry Andric     response.PutCString("ostype:macosx;");
2290b57cec5SDimitry Andric     response.Printf("watchpoint_exceptions_received:after;");
2300b57cec5SDimitry Andric   }
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric #else
2330b57cec5SDimitry Andric   if (host_arch.GetMachine() == llvm::Triple::aarch64 ||
234*9dba64beSDimitry Andric       host_arch.GetMachine() == llvm::Triple::aarch64_32 ||
2350b57cec5SDimitry Andric       host_arch.GetMachine() == llvm::Triple::aarch64_be ||
2360b57cec5SDimitry Andric       host_arch.GetMachine() == llvm::Triple::arm ||
2370b57cec5SDimitry Andric       host_arch.GetMachine() == llvm::Triple::armeb || host_arch.IsMIPS())
2380b57cec5SDimitry Andric     response.Printf("watchpoint_exceptions_received:before;");
2390b57cec5SDimitry Andric   else
2400b57cec5SDimitry Andric     response.Printf("watchpoint_exceptions_received:after;");
2410b57cec5SDimitry Andric #endif
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   switch (endian::InlHostByteOrder()) {
2440b57cec5SDimitry Andric   case eByteOrderBig:
2450b57cec5SDimitry Andric     response.PutCString("endian:big;");
2460b57cec5SDimitry Andric     break;
2470b57cec5SDimitry Andric   case eByteOrderLittle:
2480b57cec5SDimitry Andric     response.PutCString("endian:little;");
2490b57cec5SDimitry Andric     break;
2500b57cec5SDimitry Andric   case eByteOrderPDP:
2510b57cec5SDimitry Andric     response.PutCString("endian:pdp;");
2520b57cec5SDimitry Andric     break;
2530b57cec5SDimitry Andric   default:
2540b57cec5SDimitry Andric     response.PutCString("endian:unknown;");
2550b57cec5SDimitry Andric     break;
2560b57cec5SDimitry Andric   }
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric   llvm::VersionTuple version = HostInfo::GetOSVersion();
2590b57cec5SDimitry Andric   if (!version.empty()) {
2600b57cec5SDimitry Andric     response.Format("os_version:{0}", version.getAsString());
2610b57cec5SDimitry Andric     response.PutChar(';');
2620b57cec5SDimitry Andric   }
2630b57cec5SDimitry Andric 
264*9dba64beSDimitry Andric #if defined(__APPLE__)
265*9dba64beSDimitry Andric   llvm::VersionTuple maccatalyst_version = HostInfo::GetMacCatalystVersion();
266*9dba64beSDimitry Andric   if (!maccatalyst_version.empty()) {
267*9dba64beSDimitry Andric     response.Format("maccatalyst_version:{0}",
268*9dba64beSDimitry Andric                     maccatalyst_version.getAsString());
269*9dba64beSDimitry Andric     response.PutChar(';');
270*9dba64beSDimitry Andric   }
271*9dba64beSDimitry Andric #endif
272*9dba64beSDimitry Andric 
2730b57cec5SDimitry Andric   std::string s;
2740b57cec5SDimitry Andric   if (HostInfo::GetOSBuildString(s)) {
2750b57cec5SDimitry Andric     response.PutCString("os_build:");
2760b57cec5SDimitry Andric     response.PutStringAsRawHex8(s);
2770b57cec5SDimitry Andric     response.PutChar(';');
2780b57cec5SDimitry Andric   }
2790b57cec5SDimitry Andric   if (HostInfo::GetOSKernelDescription(s)) {
2800b57cec5SDimitry Andric     response.PutCString("os_kernel:");
2810b57cec5SDimitry Andric     response.PutStringAsRawHex8(s);
2820b57cec5SDimitry Andric     response.PutChar(';');
2830b57cec5SDimitry Andric   }
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric #if defined(__APPLE__)
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
2880b57cec5SDimitry Andric   // For iOS devices, we are connected through a USB Mux so we never pretend to
2890b57cec5SDimitry Andric   // actually have a hostname as far as the remote lldb that is connecting to
2900b57cec5SDimitry Andric   // this lldb-platform is concerned
2910b57cec5SDimitry Andric   response.PutCString("hostname:");
2920b57cec5SDimitry Andric   response.PutStringAsRawHex8("127.0.0.1");
2930b57cec5SDimitry Andric   response.PutChar(';');
2940b57cec5SDimitry Andric #else  // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
2950b57cec5SDimitry Andric   if (HostInfo::GetHostname(s)) {
2960b57cec5SDimitry Andric     response.PutCString("hostname:");
2970b57cec5SDimitry Andric     response.PutStringAsRawHex8(s);
2980b57cec5SDimitry Andric     response.PutChar(';');
2990b57cec5SDimitry Andric   }
3000b57cec5SDimitry Andric #endif // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric #else  // #if defined(__APPLE__)
3030b57cec5SDimitry Andric   if (HostInfo::GetHostname(s)) {
3040b57cec5SDimitry Andric     response.PutCString("hostname:");
3050b57cec5SDimitry Andric     response.PutStringAsRawHex8(s);
3060b57cec5SDimitry Andric     response.PutChar(';');
3070b57cec5SDimitry Andric   }
3080b57cec5SDimitry Andric #endif // #if defined(__APPLE__)
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric   if (g_default_packet_timeout_sec > 0)
3110b57cec5SDimitry Andric     response.Printf("default_packet_timeout:%u;", g_default_packet_timeout_sec);
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
3170b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qProcessInfoPID(
3180b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
3190b57cec5SDimitry Andric   // Packet format: "qProcessInfoPID:%i" where %i is the pid
3200b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qProcessInfoPID:"));
3210b57cec5SDimitry Andric   lldb::pid_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID);
3220b57cec5SDimitry Andric   if (pid != LLDB_INVALID_PROCESS_ID) {
3230b57cec5SDimitry Andric     ProcessInstanceInfo proc_info;
3240b57cec5SDimitry Andric     if (Host::GetProcessInfo(pid, proc_info)) {
3250b57cec5SDimitry Andric       StreamString response;
3260b57cec5SDimitry Andric       CreateProcessInfoResponse(proc_info, response);
3270b57cec5SDimitry Andric       return SendPacketNoLock(response.GetString());
3280b57cec5SDimitry Andric     }
3290b57cec5SDimitry Andric   }
3300b57cec5SDimitry Andric   return SendErrorResponse(1);
3310b57cec5SDimitry Andric }
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
3340b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo(
3350b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
3360b57cec5SDimitry Andric   m_proc_infos_index = 0;
3370b57cec5SDimitry Andric   m_proc_infos.Clear();
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric   ProcessInstanceInfoMatch match_info;
3400b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qfProcessInfo"));
3410b57cec5SDimitry Andric   if (packet.GetChar() == ':') {
3420b57cec5SDimitry Andric     llvm::StringRef key;
3430b57cec5SDimitry Andric     llvm::StringRef value;
3440b57cec5SDimitry Andric     while (packet.GetNameColonValue(key, value)) {
3450b57cec5SDimitry Andric       bool success = true;
3460b57cec5SDimitry Andric       if (key.equals("name")) {
3470b57cec5SDimitry Andric         StringExtractor extractor(value);
3480b57cec5SDimitry Andric         std::string file;
3490b57cec5SDimitry Andric         extractor.GetHexByteString(file);
3500b57cec5SDimitry Andric         match_info.GetProcessInfo().GetExecutableFile().SetFile(
3510b57cec5SDimitry Andric             file, FileSpec::Style::native);
3520b57cec5SDimitry Andric       } else if (key.equals("name_match")) {
3530b57cec5SDimitry Andric         NameMatch name_match = llvm::StringSwitch<NameMatch>(value)
3540b57cec5SDimitry Andric                                    .Case("equals", NameMatch::Equals)
3550b57cec5SDimitry Andric                                    .Case("starts_with", NameMatch::StartsWith)
3560b57cec5SDimitry Andric                                    .Case("ends_with", NameMatch::EndsWith)
3570b57cec5SDimitry Andric                                    .Case("contains", NameMatch::Contains)
3580b57cec5SDimitry Andric                                    .Case("regex", NameMatch::RegularExpression)
3590b57cec5SDimitry Andric                                    .Default(NameMatch::Ignore);
3600b57cec5SDimitry Andric         match_info.SetNameMatchType(name_match);
3610b57cec5SDimitry Andric         if (name_match == NameMatch::Ignore)
3620b57cec5SDimitry Andric           return SendErrorResponse(2);
3630b57cec5SDimitry Andric       } else if (key.equals("pid")) {
3640b57cec5SDimitry Andric         lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
3650b57cec5SDimitry Andric         if (value.getAsInteger(0, pid))
3660b57cec5SDimitry Andric           return SendErrorResponse(2);
3670b57cec5SDimitry Andric         match_info.GetProcessInfo().SetProcessID(pid);
3680b57cec5SDimitry Andric       } else if (key.equals("parent_pid")) {
3690b57cec5SDimitry Andric         lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
3700b57cec5SDimitry Andric         if (value.getAsInteger(0, pid))
3710b57cec5SDimitry Andric           return SendErrorResponse(2);
3720b57cec5SDimitry Andric         match_info.GetProcessInfo().SetParentProcessID(pid);
3730b57cec5SDimitry Andric       } else if (key.equals("uid")) {
3740b57cec5SDimitry Andric         uint32_t uid = UINT32_MAX;
3750b57cec5SDimitry Andric         if (value.getAsInteger(0, uid))
3760b57cec5SDimitry Andric           return SendErrorResponse(2);
3770b57cec5SDimitry Andric         match_info.GetProcessInfo().SetUserID(uid);
3780b57cec5SDimitry Andric       } else if (key.equals("gid")) {
3790b57cec5SDimitry Andric         uint32_t gid = UINT32_MAX;
3800b57cec5SDimitry Andric         if (value.getAsInteger(0, gid))
3810b57cec5SDimitry Andric           return SendErrorResponse(2);
3820b57cec5SDimitry Andric         match_info.GetProcessInfo().SetGroupID(gid);
3830b57cec5SDimitry Andric       } else if (key.equals("euid")) {
3840b57cec5SDimitry Andric         uint32_t uid = UINT32_MAX;
3850b57cec5SDimitry Andric         if (value.getAsInteger(0, uid))
3860b57cec5SDimitry Andric           return SendErrorResponse(2);
3870b57cec5SDimitry Andric         match_info.GetProcessInfo().SetEffectiveUserID(uid);
3880b57cec5SDimitry Andric       } else if (key.equals("egid")) {
3890b57cec5SDimitry Andric         uint32_t gid = UINT32_MAX;
3900b57cec5SDimitry Andric         if (value.getAsInteger(0, gid))
3910b57cec5SDimitry Andric           return SendErrorResponse(2);
3920b57cec5SDimitry Andric         match_info.GetProcessInfo().SetEffectiveGroupID(gid);
3930b57cec5SDimitry Andric       } else if (key.equals("all_users")) {
3940b57cec5SDimitry Andric         match_info.SetMatchAllUsers(
3950b57cec5SDimitry Andric             OptionArgParser::ToBoolean(value, false, &success));
3960b57cec5SDimitry Andric       } else if (key.equals("triple")) {
3970b57cec5SDimitry Andric         match_info.GetProcessInfo().GetArchitecture() =
3980b57cec5SDimitry Andric             HostInfo::GetAugmentedArchSpec(value);
3990b57cec5SDimitry Andric       } else {
4000b57cec5SDimitry Andric         success = false;
4010b57cec5SDimitry Andric       }
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric       if (!success)
4040b57cec5SDimitry Andric         return SendErrorResponse(2);
4050b57cec5SDimitry Andric     }
4060b57cec5SDimitry Andric   }
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric   if (Host::FindProcesses(match_info, m_proc_infos)) {
4090b57cec5SDimitry Andric     // We found something, return the first item by calling the get subsequent
4100b57cec5SDimitry Andric     // process info packet handler...
4110b57cec5SDimitry Andric     return Handle_qsProcessInfo(packet);
4120b57cec5SDimitry Andric   }
4130b57cec5SDimitry Andric   return SendErrorResponse(3);
4140b57cec5SDimitry Andric }
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
4170b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo(
4180b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
4190b57cec5SDimitry Andric   if (m_proc_infos_index < m_proc_infos.GetSize()) {
4200b57cec5SDimitry Andric     StreamString response;
4210b57cec5SDimitry Andric     CreateProcessInfoResponse(
4220b57cec5SDimitry Andric         m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
4230b57cec5SDimitry Andric     ++m_proc_infos_index;
4240b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
4250b57cec5SDimitry Andric   }
4260b57cec5SDimitry Andric   return SendErrorResponse(4);
4270b57cec5SDimitry Andric }
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
4300b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qUserName(
4310b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
4320b57cec5SDimitry Andric #if !defined(LLDB_DISABLE_POSIX)
4330b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
434*9dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__);
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric   // Packet format: "qUserName:%i" where %i is the uid
4370b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qUserName:"));
4380b57cec5SDimitry Andric   uint32_t uid = packet.GetU32(UINT32_MAX);
4390b57cec5SDimitry Andric   if (uid != UINT32_MAX) {
4400b57cec5SDimitry Andric     if (llvm::Optional<llvm::StringRef> name =
4410b57cec5SDimitry Andric             HostInfo::GetUserIDResolver().GetUserName(uid)) {
4420b57cec5SDimitry Andric       StreamString response;
4430b57cec5SDimitry Andric       response.PutStringAsRawHex8(*name);
4440b57cec5SDimitry Andric       return SendPacketNoLock(response.GetString());
4450b57cec5SDimitry Andric     }
4460b57cec5SDimitry Andric   }
447*9dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerCommon::%s end", __FUNCTION__);
4480b57cec5SDimitry Andric #endif
4490b57cec5SDimitry Andric   return SendErrorResponse(5);
4500b57cec5SDimitry Andric }
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
4530b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qGroupName(
4540b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
4550b57cec5SDimitry Andric #if !defined(LLDB_DISABLE_POSIX)
4560b57cec5SDimitry Andric   // Packet format: "qGroupName:%i" where %i is the gid
4570b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qGroupName:"));
4580b57cec5SDimitry Andric   uint32_t gid = packet.GetU32(UINT32_MAX);
4590b57cec5SDimitry Andric   if (gid != UINT32_MAX) {
4600b57cec5SDimitry Andric     if (llvm::Optional<llvm::StringRef> name =
4610b57cec5SDimitry Andric             HostInfo::GetUserIDResolver().GetGroupName(gid)) {
4620b57cec5SDimitry Andric       StreamString response;
4630b57cec5SDimitry Andric       response.PutStringAsRawHex8(*name);
4640b57cec5SDimitry Andric       return SendPacketNoLock(response.GetString());
4650b57cec5SDimitry Andric     }
4660b57cec5SDimitry Andric   }
4670b57cec5SDimitry Andric #endif
4680b57cec5SDimitry Andric   return SendErrorResponse(6);
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
4720b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qSpeedTest(
4730b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
4740b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qSpeedTest:"));
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric   llvm::StringRef key;
4770b57cec5SDimitry Andric   llvm::StringRef value;
4780b57cec5SDimitry Andric   bool success = packet.GetNameColonValue(key, value);
4790b57cec5SDimitry Andric   if (success && key.equals("response_size")) {
4800b57cec5SDimitry Andric     uint32_t response_size = 0;
4810b57cec5SDimitry Andric     if (!value.getAsInteger(0, response_size)) {
4820b57cec5SDimitry Andric       if (response_size == 0)
4830b57cec5SDimitry Andric         return SendOKResponse();
4840b57cec5SDimitry Andric       StreamString response;
4850b57cec5SDimitry Andric       uint32_t bytes_left = response_size;
4860b57cec5SDimitry Andric       response.PutCString("data:");
4870b57cec5SDimitry Andric       while (bytes_left > 0) {
4880b57cec5SDimitry Andric         if (bytes_left >= 26) {
4890b57cec5SDimitry Andric           response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
4900b57cec5SDimitry Andric           bytes_left -= 26;
4910b57cec5SDimitry Andric         } else {
4920b57cec5SDimitry Andric           response.Printf("%*.*s;", bytes_left, bytes_left,
4930b57cec5SDimitry Andric                           "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
4940b57cec5SDimitry Andric           bytes_left = 0;
4950b57cec5SDimitry Andric         }
4960b57cec5SDimitry Andric       }
4970b57cec5SDimitry Andric       return SendPacketNoLock(response.GetString());
4980b57cec5SDimitry Andric     }
4990b57cec5SDimitry Andric   }
5000b57cec5SDimitry Andric   return SendErrorResponse(7);
5010b57cec5SDimitry Andric }
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
5040b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_Open(
5050b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
5060b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:open:"));
5070b57cec5SDimitry Andric   std::string path;
5080b57cec5SDimitry Andric   packet.GetHexByteStringTerminatedBy(path, ',');
5090b57cec5SDimitry Andric   if (!path.empty()) {
5100b57cec5SDimitry Andric     if (packet.GetChar() == ',') {
511*9dba64beSDimitry Andric       // FIXME
512*9dba64beSDimitry Andric       // The flag values for OpenOptions do not match the values used by GDB
513*9dba64beSDimitry Andric       // * https://sourceware.org/gdb/onlinedocs/gdb/Open-Flags.html#Open-Flags
514*9dba64beSDimitry Andric       // * rdar://problem/46788934
515*9dba64beSDimitry Andric       auto flags = File::OpenOptions(packet.GetHexMaxU32(false, 0));
5160b57cec5SDimitry Andric       if (packet.GetChar() == ',') {
5170b57cec5SDimitry Andric         mode_t mode = packet.GetHexMaxU32(false, 0600);
5180b57cec5SDimitry Andric         FileSpec path_spec(path);
5190b57cec5SDimitry Andric         FileSystem::Instance().Resolve(path_spec);
5200b57cec5SDimitry Andric         // Do not close fd.
521*9dba64beSDimitry Andric         auto file = FileSystem::Instance().Open(path_spec, flags, mode, false);
522*9dba64beSDimitry Andric 
523*9dba64beSDimitry Andric         int save_errno = 0;
524*9dba64beSDimitry Andric         int descriptor = File::kInvalidDescriptor;
525*9dba64beSDimitry Andric         if (file) {
526*9dba64beSDimitry Andric           descriptor = file.get()->GetDescriptor();
527*9dba64beSDimitry Andric         } else {
528*9dba64beSDimitry Andric           std::error_code code = errorToErrorCode(file.takeError());
529*9dba64beSDimitry Andric           if (code.category() == std::system_category()) {
530*9dba64beSDimitry Andric             save_errno = code.value();
531*9dba64beSDimitry Andric           }
532*9dba64beSDimitry Andric         }
533*9dba64beSDimitry Andric 
5340b57cec5SDimitry Andric         StreamString response;
5350b57cec5SDimitry Andric         response.PutChar('F');
536*9dba64beSDimitry Andric         response.Printf("%i", descriptor);
5370b57cec5SDimitry Andric         if (save_errno)
5380b57cec5SDimitry Andric           response.Printf(",%i", save_errno);
5390b57cec5SDimitry Andric         return SendPacketNoLock(response.GetString());
5400b57cec5SDimitry Andric       }
5410b57cec5SDimitry Andric     }
5420b57cec5SDimitry Andric   }
5430b57cec5SDimitry Andric   return SendErrorResponse(18);
5440b57cec5SDimitry Andric }
5450b57cec5SDimitry Andric 
5460b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
5470b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_Close(
5480b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
5490b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:close:"));
5500b57cec5SDimitry Andric   int fd = packet.GetS32(-1);
5510b57cec5SDimitry Andric   int err = -1;
5520b57cec5SDimitry Andric   int save_errno = 0;
5530b57cec5SDimitry Andric   if (fd >= 0) {
554*9dba64beSDimitry Andric     NativeFile file(fd, File::OpenOptions(0), true);
5550b57cec5SDimitry Andric     Status error = file.Close();
5560b57cec5SDimitry Andric     err = 0;
5570b57cec5SDimitry Andric     save_errno = error.GetError();
5580b57cec5SDimitry Andric   } else {
5590b57cec5SDimitry Andric     save_errno = EINVAL;
5600b57cec5SDimitry Andric   }
5610b57cec5SDimitry Andric   StreamString response;
5620b57cec5SDimitry Andric   response.PutChar('F');
5630b57cec5SDimitry Andric   response.Printf("%i", err);
5640b57cec5SDimitry Andric   if (save_errno)
5650b57cec5SDimitry Andric     response.Printf(",%i", save_errno);
5660b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
5670b57cec5SDimitry Andric }
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
5700b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_pRead(
5710b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
5720b57cec5SDimitry Andric   StreamGDBRemote response;
5730b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:pread:"));
5740b57cec5SDimitry Andric   int fd = packet.GetS32(-1);
5750b57cec5SDimitry Andric   if (packet.GetChar() == ',') {
576*9dba64beSDimitry Andric     size_t count = packet.GetU64(SIZE_MAX);
5770b57cec5SDimitry Andric     if (packet.GetChar() == ',') {
5780b57cec5SDimitry Andric       off_t offset = packet.GetU64(UINT32_MAX);
579*9dba64beSDimitry Andric       if (count == SIZE_MAX) {
5800b57cec5SDimitry Andric         response.Printf("F-1:%i", EINVAL);
5810b57cec5SDimitry Andric         return SendPacketNoLock(response.GetString());
5820b57cec5SDimitry Andric       }
5830b57cec5SDimitry Andric 
5840b57cec5SDimitry Andric       std::string buffer(count, 0);
585*9dba64beSDimitry Andric       NativeFile file(fd, File::eOpenOptionRead, false);
5860b57cec5SDimitry Andric       Status error = file.Read(static_cast<void *>(&buffer[0]), count, offset);
5870b57cec5SDimitry Andric       const ssize_t bytes_read = error.Success() ? count : -1;
5880b57cec5SDimitry Andric       const int save_errno = error.GetError();
5890b57cec5SDimitry Andric       response.PutChar('F');
5900b57cec5SDimitry Andric       response.Printf("%zi", bytes_read);
5910b57cec5SDimitry Andric       if (save_errno)
5920b57cec5SDimitry Andric         response.Printf(",%i", save_errno);
5930b57cec5SDimitry Andric       else {
5940b57cec5SDimitry Andric         response.PutChar(';');
5950b57cec5SDimitry Andric         response.PutEscapedBytes(&buffer[0], bytes_read);
5960b57cec5SDimitry Andric       }
5970b57cec5SDimitry Andric       return SendPacketNoLock(response.GetString());
5980b57cec5SDimitry Andric     }
5990b57cec5SDimitry Andric   }
6000b57cec5SDimitry Andric   return SendErrorResponse(21);
6010b57cec5SDimitry Andric }
6020b57cec5SDimitry Andric 
6030b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
6040b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite(
6050b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
6060b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:pwrite:"));
6070b57cec5SDimitry Andric 
6080b57cec5SDimitry Andric   StreamGDBRemote response;
6090b57cec5SDimitry Andric   response.PutChar('F');
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric   int fd = packet.GetU32(UINT32_MAX);
6120b57cec5SDimitry Andric   if (packet.GetChar() == ',') {
6130b57cec5SDimitry Andric     off_t offset = packet.GetU64(UINT32_MAX);
6140b57cec5SDimitry Andric     if (packet.GetChar() == ',') {
6150b57cec5SDimitry Andric       std::string buffer;
6160b57cec5SDimitry Andric       if (packet.GetEscapedBinaryData(buffer)) {
617*9dba64beSDimitry Andric         NativeFile file(fd, File::eOpenOptionWrite, false);
6180b57cec5SDimitry Andric         size_t count = buffer.size();
6190b57cec5SDimitry Andric         Status error =
6200b57cec5SDimitry Andric             file.Write(static_cast<const void *>(&buffer[0]), count, offset);
6210b57cec5SDimitry Andric         const ssize_t bytes_written = error.Success() ? count : -1;
6220b57cec5SDimitry Andric         const int save_errno = error.GetError();
6230b57cec5SDimitry Andric         response.Printf("%zi", bytes_written);
6240b57cec5SDimitry Andric         if (save_errno)
6250b57cec5SDimitry Andric           response.Printf(",%i", save_errno);
6260b57cec5SDimitry Andric       } else {
6270b57cec5SDimitry Andric         response.Printf("-1,%i", EINVAL);
6280b57cec5SDimitry Andric       }
6290b57cec5SDimitry Andric       return SendPacketNoLock(response.GetString());
6300b57cec5SDimitry Andric     }
6310b57cec5SDimitry Andric   }
6320b57cec5SDimitry Andric   return SendErrorResponse(27);
6330b57cec5SDimitry Andric }
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
6360b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_Size(
6370b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
6380b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:size:"));
6390b57cec5SDimitry Andric   std::string path;
6400b57cec5SDimitry Andric   packet.GetHexByteString(path);
6410b57cec5SDimitry Andric   if (!path.empty()) {
6420b57cec5SDimitry Andric     uint64_t Size;
6430b57cec5SDimitry Andric     if (llvm::sys::fs::file_size(path, Size))
6440b57cec5SDimitry Andric       return SendErrorResponse(5);
6450b57cec5SDimitry Andric     StreamString response;
6460b57cec5SDimitry Andric     response.PutChar('F');
6470b57cec5SDimitry Andric     response.PutHex64(Size);
6480b57cec5SDimitry Andric     if (Size == UINT64_MAX) {
6490b57cec5SDimitry Andric       response.PutChar(',');
6500b57cec5SDimitry Andric       response.PutHex64(Size); // TODO: replace with Host::GetSyswideErrorCode()
6510b57cec5SDimitry Andric     }
6520b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
6530b57cec5SDimitry Andric   }
6540b57cec5SDimitry Andric   return SendErrorResponse(22);
6550b57cec5SDimitry Andric }
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
6580b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_Mode(
6590b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
6600b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:mode:"));
6610b57cec5SDimitry Andric   std::string path;
6620b57cec5SDimitry Andric   packet.GetHexByteString(path);
6630b57cec5SDimitry Andric   if (!path.empty()) {
6640b57cec5SDimitry Andric     FileSpec file_spec(path);
6650b57cec5SDimitry Andric     FileSystem::Instance().Resolve(file_spec);
6660b57cec5SDimitry Andric     std::error_code ec;
6670b57cec5SDimitry Andric     const uint32_t mode = FileSystem::Instance().GetPermissions(file_spec, ec);
6680b57cec5SDimitry Andric     StreamString response;
6690b57cec5SDimitry Andric     response.Printf("F%u", mode);
6700b57cec5SDimitry Andric     if (mode == 0 || ec)
6710b57cec5SDimitry Andric       response.Printf(",%i", (int)Status(ec).GetError());
6720b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
6730b57cec5SDimitry Andric   }
6740b57cec5SDimitry Andric   return SendErrorResponse(23);
6750b57cec5SDimitry Andric }
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
6780b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_Exists(
6790b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
6800b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:exists:"));
6810b57cec5SDimitry Andric   std::string path;
6820b57cec5SDimitry Andric   packet.GetHexByteString(path);
6830b57cec5SDimitry Andric   if (!path.empty()) {
6840b57cec5SDimitry Andric     bool retcode = llvm::sys::fs::exists(path);
6850b57cec5SDimitry Andric     StreamString response;
6860b57cec5SDimitry Andric     response.PutChar('F');
6870b57cec5SDimitry Andric     response.PutChar(',');
6880b57cec5SDimitry Andric     if (retcode)
6890b57cec5SDimitry Andric       response.PutChar('1');
6900b57cec5SDimitry Andric     else
6910b57cec5SDimitry Andric       response.PutChar('0');
6920b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
6930b57cec5SDimitry Andric   }
6940b57cec5SDimitry Andric   return SendErrorResponse(24);
6950b57cec5SDimitry Andric }
6960b57cec5SDimitry Andric 
6970b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
6980b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_symlink(
6990b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
7000b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:symlink:"));
7010b57cec5SDimitry Andric   std::string dst, src;
7020b57cec5SDimitry Andric   packet.GetHexByteStringTerminatedBy(dst, ',');
7030b57cec5SDimitry Andric   packet.GetChar(); // Skip ',' char
7040b57cec5SDimitry Andric   packet.GetHexByteString(src);
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric   FileSpec src_spec(src);
7070b57cec5SDimitry Andric   FileSystem::Instance().Resolve(src_spec);
7080b57cec5SDimitry Andric   Status error = FileSystem::Instance().Symlink(src_spec, FileSpec(dst));
7090b57cec5SDimitry Andric 
7100b57cec5SDimitry Andric   StreamString response;
7110b57cec5SDimitry Andric   response.Printf("F%u,%u", error.GetError(), error.GetError());
7120b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
7130b57cec5SDimitry Andric }
7140b57cec5SDimitry Andric 
7150b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
7160b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_unlink(
7170b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
7180b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:unlink:"));
7190b57cec5SDimitry Andric   std::string path;
7200b57cec5SDimitry Andric   packet.GetHexByteString(path);
7210b57cec5SDimitry Andric   Status error(llvm::sys::fs::remove(path));
7220b57cec5SDimitry Andric   StreamString response;
7230b57cec5SDimitry Andric   response.Printf("F%u,%u", error.GetError(), error.GetError());
7240b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
7280b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell(
7290b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
7300b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qPlatform_shell:"));
7310b57cec5SDimitry Andric   std::string path;
7320b57cec5SDimitry Andric   std::string working_dir;
7330b57cec5SDimitry Andric   packet.GetHexByteStringTerminatedBy(path, ',');
7340b57cec5SDimitry Andric   if (!path.empty()) {
7350b57cec5SDimitry Andric     if (packet.GetChar() == ',') {
7360b57cec5SDimitry Andric       // FIXME: add timeout to qPlatform_shell packet
7370b57cec5SDimitry Andric       // uint32_t timeout = packet.GetHexMaxU32(false, 32);
7380b57cec5SDimitry Andric       if (packet.GetChar() == ',')
7390b57cec5SDimitry Andric         packet.GetHexByteString(working_dir);
7400b57cec5SDimitry Andric       int status, signo;
7410b57cec5SDimitry Andric       std::string output;
7420b57cec5SDimitry Andric       FileSpec working_spec(working_dir);
7430b57cec5SDimitry Andric       FileSystem::Instance().Resolve(working_spec);
7440b57cec5SDimitry Andric       Status err =
7450b57cec5SDimitry Andric           Host::RunShellCommand(path.c_str(), working_spec, &status, &signo,
7460b57cec5SDimitry Andric                                 &output, std::chrono::seconds(10));
7470b57cec5SDimitry Andric       StreamGDBRemote response;
7480b57cec5SDimitry Andric       if (err.Fail()) {
7490b57cec5SDimitry Andric         response.PutCString("F,");
7500b57cec5SDimitry Andric         response.PutHex32(UINT32_MAX);
7510b57cec5SDimitry Andric       } else {
7520b57cec5SDimitry Andric         response.PutCString("F,");
7530b57cec5SDimitry Andric         response.PutHex32(status);
7540b57cec5SDimitry Andric         response.PutChar(',');
7550b57cec5SDimitry Andric         response.PutHex32(signo);
7560b57cec5SDimitry Andric         response.PutChar(',');
7570b57cec5SDimitry Andric         response.PutEscapedBytes(output.c_str(), output.size());
7580b57cec5SDimitry Andric       }
7590b57cec5SDimitry Andric       return SendPacketNoLock(response.GetString());
7600b57cec5SDimitry Andric     }
7610b57cec5SDimitry Andric   }
7620b57cec5SDimitry Andric   return SendErrorResponse(24);
7630b57cec5SDimitry Andric }
7640b57cec5SDimitry Andric 
7650b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
7660b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_Stat(
7670b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
7680b57cec5SDimitry Andric   return SendUnimplementedResponse(
7690b57cec5SDimitry Andric       "GDBRemoteCommunicationServerCommon::Handle_vFile_Stat() unimplemented");
7700b57cec5SDimitry Andric }
7710b57cec5SDimitry Andric 
7720b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
7730b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_MD5(
7740b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
7750b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vFile:MD5:"));
7760b57cec5SDimitry Andric   std::string path;
7770b57cec5SDimitry Andric   packet.GetHexByteString(path);
7780b57cec5SDimitry Andric   if (!path.empty()) {
7790b57cec5SDimitry Andric     StreamGDBRemote response;
7800b57cec5SDimitry Andric     auto Result = llvm::sys::fs::md5_contents(path);
7810b57cec5SDimitry Andric     if (!Result) {
7820b57cec5SDimitry Andric       response.PutCString("F,");
7830b57cec5SDimitry Andric       response.PutCString("x");
7840b57cec5SDimitry Andric     } else {
7850b57cec5SDimitry Andric       response.PutCString("F,");
7860b57cec5SDimitry Andric       response.PutHex64(Result->low());
7870b57cec5SDimitry Andric       response.PutHex64(Result->high());
7880b57cec5SDimitry Andric     }
7890b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
7900b57cec5SDimitry Andric   }
7910b57cec5SDimitry Andric   return SendErrorResponse(25);
7920b57cec5SDimitry Andric }
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
7950b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir(
7960b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
7970b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qPlatform_mkdir:"));
7980b57cec5SDimitry Andric   mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
7990b57cec5SDimitry Andric   if (packet.GetChar() == ',') {
8000b57cec5SDimitry Andric     std::string path;
8010b57cec5SDimitry Andric     packet.GetHexByteString(path);
8020b57cec5SDimitry Andric     Status error(llvm::sys::fs::create_directory(path, mode));
8030b57cec5SDimitry Andric 
8040b57cec5SDimitry Andric     StreamGDBRemote response;
8050b57cec5SDimitry Andric     response.Printf("F%u", error.GetError());
8060b57cec5SDimitry Andric 
8070b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
8080b57cec5SDimitry Andric   }
8090b57cec5SDimitry Andric   return SendErrorResponse(20);
8100b57cec5SDimitry Andric }
8110b57cec5SDimitry Andric 
8120b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
8130b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod(
8140b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
8150b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qPlatform_chmod:"));
8160b57cec5SDimitry Andric 
8170b57cec5SDimitry Andric   auto perms =
8180b57cec5SDimitry Andric       static_cast<llvm::sys::fs::perms>(packet.GetHexMaxU32(false, UINT32_MAX));
8190b57cec5SDimitry Andric   if (packet.GetChar() == ',') {
8200b57cec5SDimitry Andric     std::string path;
8210b57cec5SDimitry Andric     packet.GetHexByteString(path);
8220b57cec5SDimitry Andric     Status error(llvm::sys::fs::setPermissions(path, perms));
8230b57cec5SDimitry Andric 
8240b57cec5SDimitry Andric     StreamGDBRemote response;
8250b57cec5SDimitry Andric     response.Printf("F%u", error.GetError());
8260b57cec5SDimitry Andric 
8270b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
8280b57cec5SDimitry Andric   }
8290b57cec5SDimitry Andric   return SendErrorResponse(19);
8300b57cec5SDimitry Andric }
8310b57cec5SDimitry Andric 
8320b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
8330b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qSupported(
8340b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
8350b57cec5SDimitry Andric   StreamGDBRemote response;
8360b57cec5SDimitry Andric 
8370b57cec5SDimitry Andric   // Features common to lldb-platform and llgs.
8380b57cec5SDimitry Andric   uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet
8390b57cec5SDimitry Andric                                          // size--debugger can always use less
8400b57cec5SDimitry Andric   response.Printf("PacketSize=%x", max_packet_size);
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric   response.PutCString(";QStartNoAckMode+");
8430b57cec5SDimitry Andric   response.PutCString(";QThreadSuffixSupported+");
8440b57cec5SDimitry Andric   response.PutCString(";QListThreadsInStopReply+");
8450b57cec5SDimitry Andric   response.PutCString(";qEcho+");
8460b57cec5SDimitry Andric #if defined(__linux__) || defined(__NetBSD__)
8470b57cec5SDimitry Andric   response.PutCString(";QPassSignals+");
8480b57cec5SDimitry Andric   response.PutCString(";qXfer:auxv:read+");
849*9dba64beSDimitry Andric   response.PutCString(";qXfer:libraries-svr4:read+");
8500b57cec5SDimitry Andric #endif
8510b57cec5SDimitry Andric 
8520b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
8530b57cec5SDimitry Andric }
8540b57cec5SDimitry Andric 
8550b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
8560b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported(
8570b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
8580b57cec5SDimitry Andric   m_thread_suffix_supported = true;
8590b57cec5SDimitry Andric   return SendOKResponse();
8600b57cec5SDimitry Andric }
8610b57cec5SDimitry Andric 
8620b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
8630b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply(
8640b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
8650b57cec5SDimitry Andric   m_list_threads_in_stop_reply = true;
8660b57cec5SDimitry Andric   return SendOKResponse();
8670b57cec5SDimitry Andric }
8680b57cec5SDimitry Andric 
8690b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
8700b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError(
8710b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
8720b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QSetDetachOnError:"));
8730b57cec5SDimitry Andric   if (packet.GetU32(0))
8740b57cec5SDimitry Andric     m_process_launch_info.GetFlags().Set(eLaunchFlagDetachOnError);
8750b57cec5SDimitry Andric   else
8760b57cec5SDimitry Andric     m_process_launch_info.GetFlags().Clear(eLaunchFlagDetachOnError);
8770b57cec5SDimitry Andric   return SendOKResponse();
8780b57cec5SDimitry Andric }
8790b57cec5SDimitry Andric 
8800b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
8810b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode(
8820b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
8830b57cec5SDimitry Andric   // Send response first before changing m_send_acks to we ack this packet
8840b57cec5SDimitry Andric   PacketResult packet_result = SendOKResponse();
8850b57cec5SDimitry Andric   m_send_acks = false;
8860b57cec5SDimitry Andric   return packet_result;
8870b57cec5SDimitry Andric }
8880b57cec5SDimitry Andric 
8890b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
8900b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN(
8910b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
8920b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QSetSTDIN:"));
8930b57cec5SDimitry Andric   FileAction file_action;
8940b57cec5SDimitry Andric   std::string path;
8950b57cec5SDimitry Andric   packet.GetHexByteString(path);
8960b57cec5SDimitry Andric   const bool read = true;
8970b57cec5SDimitry Andric   const bool write = false;
8980b57cec5SDimitry Andric   if (file_action.Open(STDIN_FILENO, FileSpec(path), read, write)) {
8990b57cec5SDimitry Andric     m_process_launch_info.AppendFileAction(file_action);
9000b57cec5SDimitry Andric     return SendOKResponse();
9010b57cec5SDimitry Andric   }
9020b57cec5SDimitry Andric   return SendErrorResponse(15);
9030b57cec5SDimitry Andric }
9040b57cec5SDimitry Andric 
9050b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
9060b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT(
9070b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
9080b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QSetSTDOUT:"));
9090b57cec5SDimitry Andric   FileAction file_action;
9100b57cec5SDimitry Andric   std::string path;
9110b57cec5SDimitry Andric   packet.GetHexByteString(path);
9120b57cec5SDimitry Andric   const bool read = false;
9130b57cec5SDimitry Andric   const bool write = true;
9140b57cec5SDimitry Andric   if (file_action.Open(STDOUT_FILENO, FileSpec(path), read, write)) {
9150b57cec5SDimitry Andric     m_process_launch_info.AppendFileAction(file_action);
9160b57cec5SDimitry Andric     return SendOKResponse();
9170b57cec5SDimitry Andric   }
9180b57cec5SDimitry Andric   return SendErrorResponse(16);
9190b57cec5SDimitry Andric }
9200b57cec5SDimitry Andric 
9210b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
9220b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR(
9230b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
9240b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QSetSTDERR:"));
9250b57cec5SDimitry Andric   FileAction file_action;
9260b57cec5SDimitry Andric   std::string path;
9270b57cec5SDimitry Andric   packet.GetHexByteString(path);
9280b57cec5SDimitry Andric   const bool read = false;
9290b57cec5SDimitry Andric   const bool write = true;
9300b57cec5SDimitry Andric   if (file_action.Open(STDERR_FILENO, FileSpec(path), read, write)) {
9310b57cec5SDimitry Andric     m_process_launch_info.AppendFileAction(file_action);
9320b57cec5SDimitry Andric     return SendOKResponse();
9330b57cec5SDimitry Andric   }
9340b57cec5SDimitry Andric   return SendErrorResponse(17);
9350b57cec5SDimitry Andric }
9360b57cec5SDimitry Andric 
9370b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
9380b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess(
9390b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
9400b57cec5SDimitry Andric   if (m_process_launch_error.Success())
9410b57cec5SDimitry Andric     return SendOKResponse();
9420b57cec5SDimitry Andric   StreamString response;
9430b57cec5SDimitry Andric   response.PutChar('E');
9440b57cec5SDimitry Andric   response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
9450b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
9460b57cec5SDimitry Andric }
9470b57cec5SDimitry Andric 
9480b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
9490b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QEnvironment(
9500b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
9510b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QEnvironment:"));
9520b57cec5SDimitry Andric   const uint32_t bytes_left = packet.GetBytesLeft();
9530b57cec5SDimitry Andric   if (bytes_left > 0) {
9540b57cec5SDimitry Andric     m_process_launch_info.GetEnvironment().insert(packet.Peek());
9550b57cec5SDimitry Andric     return SendOKResponse();
9560b57cec5SDimitry Andric   }
9570b57cec5SDimitry Andric   return SendErrorResponse(12);
9580b57cec5SDimitry Andric }
9590b57cec5SDimitry Andric 
9600b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
9610b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded(
9620b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
9630b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QEnvironmentHexEncoded:"));
9640b57cec5SDimitry Andric   const uint32_t bytes_left = packet.GetBytesLeft();
9650b57cec5SDimitry Andric   if (bytes_left > 0) {
9660b57cec5SDimitry Andric     std::string str;
9670b57cec5SDimitry Andric     packet.GetHexByteString(str);
9680b57cec5SDimitry Andric     m_process_launch_info.GetEnvironment().insert(str);
9690b57cec5SDimitry Andric     return SendOKResponse();
9700b57cec5SDimitry Andric   }
9710b57cec5SDimitry Andric   return SendErrorResponse(12);
9720b57cec5SDimitry Andric }
9730b57cec5SDimitry Andric 
9740b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
9750b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QLaunchArch(
9760b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
9770b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QLaunchArch:"));
9780b57cec5SDimitry Andric   const uint32_t bytes_left = packet.GetBytesLeft();
9790b57cec5SDimitry Andric   if (bytes_left > 0) {
9800b57cec5SDimitry Andric     const char *arch_triple = packet.Peek();
9810b57cec5SDimitry Andric     m_process_launch_info.SetArchitecture(
9820b57cec5SDimitry Andric         HostInfo::GetAugmentedArchSpec(arch_triple));
9830b57cec5SDimitry Andric     return SendOKResponse();
9840b57cec5SDimitry Andric   }
9850b57cec5SDimitry Andric   return SendErrorResponse(13);
9860b57cec5SDimitry Andric }
9870b57cec5SDimitry Andric 
9880b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
9890b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
9900b57cec5SDimitry Andric   // The 'A' packet is the most over designed packet ever here with redundant
9910b57cec5SDimitry Andric   // argument indexes, redundant argument lengths and needed hex encoded
9920b57cec5SDimitry Andric   // argument string values. Really all that is needed is a comma separated hex
9930b57cec5SDimitry Andric   // encoded argument value list, but we will stay true to the documented
9940b57cec5SDimitry Andric   // version of the 'A' packet here...
9950b57cec5SDimitry Andric 
9960b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
9970b57cec5SDimitry Andric   int actual_arg_index = 0;
9980b57cec5SDimitry Andric 
9990b57cec5SDimitry Andric   packet.SetFilePos(1); // Skip the 'A'
10000b57cec5SDimitry Andric   bool success = true;
10010b57cec5SDimitry Andric   while (success && packet.GetBytesLeft() > 0) {
10020b57cec5SDimitry Andric     // Decode the decimal argument string length. This length is the number of
10030b57cec5SDimitry Andric     // hex nibbles in the argument string value.
10040b57cec5SDimitry Andric     const uint32_t arg_len = packet.GetU32(UINT32_MAX);
10050b57cec5SDimitry Andric     if (arg_len == UINT32_MAX)
10060b57cec5SDimitry Andric       success = false;
10070b57cec5SDimitry Andric     else {
10080b57cec5SDimitry Andric       // Make sure the argument hex string length is followed by a comma
10090b57cec5SDimitry Andric       if (packet.GetChar() != ',')
10100b57cec5SDimitry Andric         success = false;
10110b57cec5SDimitry Andric       else {
10120b57cec5SDimitry Andric         // Decode the argument index. We ignore this really because who would
10130b57cec5SDimitry Andric         // really send down the arguments in a random order???
10140b57cec5SDimitry Andric         const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
10150b57cec5SDimitry Andric         if (arg_idx == UINT32_MAX)
10160b57cec5SDimitry Andric           success = false;
10170b57cec5SDimitry Andric         else {
10180b57cec5SDimitry Andric           // Make sure the argument index is followed by a comma
10190b57cec5SDimitry Andric           if (packet.GetChar() != ',')
10200b57cec5SDimitry Andric             success = false;
10210b57cec5SDimitry Andric           else {
10220b57cec5SDimitry Andric             // Decode the argument string value from hex bytes back into a UTF8
10230b57cec5SDimitry Andric             // string and make sure the length matches the one supplied in the
10240b57cec5SDimitry Andric             // packet
10250b57cec5SDimitry Andric             std::string arg;
10260b57cec5SDimitry Andric             if (packet.GetHexByteStringFixedLength(arg, arg_len) !=
10270b57cec5SDimitry Andric                 (arg_len / 2))
10280b57cec5SDimitry Andric               success = false;
10290b57cec5SDimitry Andric             else {
10300b57cec5SDimitry Andric               // If there are any bytes left
10310b57cec5SDimitry Andric               if (packet.GetBytesLeft()) {
10320b57cec5SDimitry Andric                 if (packet.GetChar() != ',')
10330b57cec5SDimitry Andric                   success = false;
10340b57cec5SDimitry Andric               }
10350b57cec5SDimitry Andric 
10360b57cec5SDimitry Andric               if (success) {
10370b57cec5SDimitry Andric                 if (arg_idx == 0)
10380b57cec5SDimitry Andric                   m_process_launch_info.GetExecutableFile().SetFile(
10390b57cec5SDimitry Andric                       arg, FileSpec::Style::native);
10400b57cec5SDimitry Andric                 m_process_launch_info.GetArguments().AppendArgument(arg);
1041*9dba64beSDimitry Andric                 LLDB_LOGF(log, "LLGSPacketHandler::%s added arg %d: \"%s\"",
10420b57cec5SDimitry Andric                           __FUNCTION__, actual_arg_index, arg.c_str());
10430b57cec5SDimitry Andric                 ++actual_arg_index;
10440b57cec5SDimitry Andric               }
10450b57cec5SDimitry Andric             }
10460b57cec5SDimitry Andric           }
10470b57cec5SDimitry Andric         }
10480b57cec5SDimitry Andric       }
10490b57cec5SDimitry Andric     }
10500b57cec5SDimitry Andric   }
10510b57cec5SDimitry Andric 
10520b57cec5SDimitry Andric   if (success) {
10530b57cec5SDimitry Andric     m_process_launch_error = LaunchProcess();
10540b57cec5SDimitry Andric     if (m_process_launch_error.Success())
10550b57cec5SDimitry Andric       return SendOKResponse();
10560b57cec5SDimitry Andric     LLDB_LOG(log, "failed to launch exe: {0}", m_process_launch_error);
10570b57cec5SDimitry Andric   }
10580b57cec5SDimitry Andric   return SendErrorResponse(8);
10590b57cec5SDimitry Andric }
10600b57cec5SDimitry Andric 
10610b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
10620b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qEcho(
10630b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
10640b57cec5SDimitry Andric   // Just echo back the exact same packet for qEcho...
10650b57cec5SDimitry Andric   return SendPacketNoLock(packet.GetStringRef());
10660b57cec5SDimitry Andric }
10670b57cec5SDimitry Andric 
10680b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
10690b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qModuleInfo(
10700b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
10710b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qModuleInfo:"));
10720b57cec5SDimitry Andric 
10730b57cec5SDimitry Andric   std::string module_path;
10740b57cec5SDimitry Andric   packet.GetHexByteStringTerminatedBy(module_path, ';');
10750b57cec5SDimitry Andric   if (module_path.empty())
10760b57cec5SDimitry Andric     return SendErrorResponse(1);
10770b57cec5SDimitry Andric 
10780b57cec5SDimitry Andric   if (packet.GetChar() != ';')
10790b57cec5SDimitry Andric     return SendErrorResponse(2);
10800b57cec5SDimitry Andric 
10810b57cec5SDimitry Andric   std::string triple;
10820b57cec5SDimitry Andric   packet.GetHexByteString(triple);
10830b57cec5SDimitry Andric 
10840b57cec5SDimitry Andric   ModuleSpec matched_module_spec = GetModuleInfo(module_path, triple);
10850b57cec5SDimitry Andric   if (!matched_module_spec.GetFileSpec())
10860b57cec5SDimitry Andric     return SendErrorResponse(3);
10870b57cec5SDimitry Andric 
10880b57cec5SDimitry Andric   const auto file_offset = matched_module_spec.GetObjectOffset();
10890b57cec5SDimitry Andric   const auto file_size = matched_module_spec.GetObjectSize();
10900b57cec5SDimitry Andric   const auto uuid_str = matched_module_spec.GetUUID().GetAsString("");
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric   StreamGDBRemote response;
10930b57cec5SDimitry Andric 
10940b57cec5SDimitry Andric   if (uuid_str.empty()) {
10950b57cec5SDimitry Andric     auto Result = llvm::sys::fs::md5_contents(
10960b57cec5SDimitry Andric         matched_module_spec.GetFileSpec().GetPath());
10970b57cec5SDimitry Andric     if (!Result)
10980b57cec5SDimitry Andric       return SendErrorResponse(5);
10990b57cec5SDimitry Andric     response.PutCString("md5:");
11000b57cec5SDimitry Andric     response.PutStringAsRawHex8(Result->digest());
11010b57cec5SDimitry Andric   } else {
11020b57cec5SDimitry Andric     response.PutCString("uuid:");
11030b57cec5SDimitry Andric     response.PutStringAsRawHex8(uuid_str);
11040b57cec5SDimitry Andric   }
11050b57cec5SDimitry Andric   response.PutChar(';');
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric   const auto &module_arch = matched_module_spec.GetArchitecture();
11080b57cec5SDimitry Andric   response.PutCString("triple:");
11090b57cec5SDimitry Andric   response.PutStringAsRawHex8(module_arch.GetTriple().getTriple());
11100b57cec5SDimitry Andric   response.PutChar(';');
11110b57cec5SDimitry Andric 
11120b57cec5SDimitry Andric   response.PutCString("file_path:");
11130b57cec5SDimitry Andric   response.PutStringAsRawHex8(matched_module_spec.GetFileSpec().GetCString());
11140b57cec5SDimitry Andric   response.PutChar(';');
11150b57cec5SDimitry Andric   response.PutCString("file_offset:");
11160b57cec5SDimitry Andric   response.PutHex64(file_offset);
11170b57cec5SDimitry Andric   response.PutChar(';');
11180b57cec5SDimitry Andric   response.PutCString("file_size:");
11190b57cec5SDimitry Andric   response.PutHex64(file_size);
11200b57cec5SDimitry Andric   response.PutChar(';');
11210b57cec5SDimitry Andric 
11220b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
11230b57cec5SDimitry Andric }
11240b57cec5SDimitry Andric 
11250b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
11260b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_jModulesInfo(
11270b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
1128*9dba64beSDimitry Andric   namespace json = llvm::json;
1129*9dba64beSDimitry Andric 
11300b57cec5SDimitry Andric   packet.SetFilePos(::strlen("jModulesInfo:"));
11310b57cec5SDimitry Andric 
11320b57cec5SDimitry Andric   StructuredData::ObjectSP object_sp = StructuredData::ParseJSON(packet.Peek());
11330b57cec5SDimitry Andric   if (!object_sp)
11340b57cec5SDimitry Andric     return SendErrorResponse(1);
11350b57cec5SDimitry Andric 
11360b57cec5SDimitry Andric   StructuredData::Array *packet_array = object_sp->GetAsArray();
11370b57cec5SDimitry Andric   if (!packet_array)
11380b57cec5SDimitry Andric     return SendErrorResponse(2);
11390b57cec5SDimitry Andric 
1140*9dba64beSDimitry Andric   json::Array response_array;
11410b57cec5SDimitry Andric   for (size_t i = 0; i < packet_array->GetSize(); ++i) {
11420b57cec5SDimitry Andric     StructuredData::Dictionary *query =
11430b57cec5SDimitry Andric         packet_array->GetItemAtIndex(i)->GetAsDictionary();
11440b57cec5SDimitry Andric     if (!query)
11450b57cec5SDimitry Andric       continue;
11460b57cec5SDimitry Andric     llvm::StringRef file, triple;
11470b57cec5SDimitry Andric     if (!query->GetValueForKeyAsString("file", file) ||
11480b57cec5SDimitry Andric         !query->GetValueForKeyAsString("triple", triple))
11490b57cec5SDimitry Andric       continue;
11500b57cec5SDimitry Andric 
11510b57cec5SDimitry Andric     ModuleSpec matched_module_spec = GetModuleInfo(file, triple);
11520b57cec5SDimitry Andric     if (!matched_module_spec.GetFileSpec())
11530b57cec5SDimitry Andric       continue;
11540b57cec5SDimitry Andric 
11550b57cec5SDimitry Andric     const auto file_offset = matched_module_spec.GetObjectOffset();
11560b57cec5SDimitry Andric     const auto file_size = matched_module_spec.GetObjectSize();
11570b57cec5SDimitry Andric     const auto uuid_str = matched_module_spec.GetUUID().GetAsString("");
11580b57cec5SDimitry Andric     if (uuid_str.empty())
11590b57cec5SDimitry Andric       continue;
1160*9dba64beSDimitry Andric     const auto triple_str =
1161*9dba64beSDimitry Andric         matched_module_spec.GetArchitecture().GetTriple().getTriple();
1162*9dba64beSDimitry Andric     const auto file_path = matched_module_spec.GetFileSpec().GetPath();
11630b57cec5SDimitry Andric 
1164*9dba64beSDimitry Andric     json::Object response{{"uuid", uuid_str},
1165*9dba64beSDimitry Andric                           {"triple", triple_str},
1166*9dba64beSDimitry Andric                           {"file_path", file_path},
1167*9dba64beSDimitry Andric                           {"file_offset", static_cast<int64_t>(file_offset)},
1168*9dba64beSDimitry Andric                           {"file_size", static_cast<int64_t>(file_size)}};
1169*9dba64beSDimitry Andric     response_array.push_back(std::move(response));
11700b57cec5SDimitry Andric   }
11710b57cec5SDimitry Andric 
11720b57cec5SDimitry Andric   StreamString response;
1173*9dba64beSDimitry Andric   response.AsRawOstream() << std::move(response_array);
11740b57cec5SDimitry Andric   StreamGDBRemote escaped_response;
11750b57cec5SDimitry Andric   escaped_response.PutEscapedBytes(response.GetString().data(),
11760b57cec5SDimitry Andric                                    response.GetSize());
11770b57cec5SDimitry Andric   return SendPacketNoLock(escaped_response.GetString());
11780b57cec5SDimitry Andric }
11790b57cec5SDimitry Andric 
11800b57cec5SDimitry Andric void GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse(
11810b57cec5SDimitry Andric     const ProcessInstanceInfo &proc_info, StreamString &response) {
11820b57cec5SDimitry Andric   response.Printf(
11830b57cec5SDimitry Andric       "pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;",
11840b57cec5SDimitry Andric       proc_info.GetProcessID(), proc_info.GetParentProcessID(),
11850b57cec5SDimitry Andric       proc_info.GetUserID(), proc_info.GetGroupID(),
11860b57cec5SDimitry Andric       proc_info.GetEffectiveUserID(), proc_info.GetEffectiveGroupID());
11870b57cec5SDimitry Andric   response.PutCString("name:");
11880b57cec5SDimitry Andric   response.PutStringAsRawHex8(proc_info.GetExecutableFile().GetCString());
1189*9dba64beSDimitry Andric 
1190*9dba64beSDimitry Andric   response.PutChar(';');
1191*9dba64beSDimitry Andric   response.PutCString("args:");
1192*9dba64beSDimitry Andric   response.PutStringAsRawHex8(proc_info.GetArg0());
1193*9dba64beSDimitry Andric   for (auto &arg : proc_info.GetArguments()) {
1194*9dba64beSDimitry Andric     response.PutChar('-');
1195*9dba64beSDimitry Andric     response.PutStringAsRawHex8(arg.ref());
1196*9dba64beSDimitry Andric   }
1197*9dba64beSDimitry Andric 
11980b57cec5SDimitry Andric   response.PutChar(';');
11990b57cec5SDimitry Andric   const ArchSpec &proc_arch = proc_info.GetArchitecture();
12000b57cec5SDimitry Andric   if (proc_arch.IsValid()) {
12010b57cec5SDimitry Andric     const llvm::Triple &proc_triple = proc_arch.GetTriple();
12020b57cec5SDimitry Andric     response.PutCString("triple:");
12030b57cec5SDimitry Andric     response.PutStringAsRawHex8(proc_triple.getTriple());
12040b57cec5SDimitry Andric     response.PutChar(';');
12050b57cec5SDimitry Andric   }
12060b57cec5SDimitry Andric }
12070b57cec5SDimitry Andric 
12080b57cec5SDimitry Andric void GDBRemoteCommunicationServerCommon::
12090b57cec5SDimitry Andric     CreateProcessInfoResponse_DebugServerStyle(
12100b57cec5SDimitry Andric         const ProcessInstanceInfo &proc_info, StreamString &response) {
12110b57cec5SDimitry Andric   response.Printf("pid:%" PRIx64 ";parent-pid:%" PRIx64
12120b57cec5SDimitry Andric                   ";real-uid:%x;real-gid:%x;effective-uid:%x;effective-gid:%x;",
12130b57cec5SDimitry Andric                   proc_info.GetProcessID(), proc_info.GetParentProcessID(),
12140b57cec5SDimitry Andric                   proc_info.GetUserID(), proc_info.GetGroupID(),
12150b57cec5SDimitry Andric                   proc_info.GetEffectiveUserID(),
12160b57cec5SDimitry Andric                   proc_info.GetEffectiveGroupID());
12170b57cec5SDimitry Andric 
12180b57cec5SDimitry Andric   const ArchSpec &proc_arch = proc_info.GetArchitecture();
12190b57cec5SDimitry Andric   if (proc_arch.IsValid()) {
12200b57cec5SDimitry Andric     const llvm::Triple &proc_triple = proc_arch.GetTriple();
12210b57cec5SDimitry Andric #if defined(__APPLE__)
12220b57cec5SDimitry Andric     // We'll send cputype/cpusubtype.
12230b57cec5SDimitry Andric     const uint32_t cpu_type = proc_arch.GetMachOCPUType();
12240b57cec5SDimitry Andric     if (cpu_type != 0)
12250b57cec5SDimitry Andric       response.Printf("cputype:%" PRIx32 ";", cpu_type);
12260b57cec5SDimitry Andric 
12270b57cec5SDimitry Andric     const uint32_t cpu_subtype = proc_arch.GetMachOCPUSubType();
12280b57cec5SDimitry Andric     if (cpu_subtype != 0)
12290b57cec5SDimitry Andric       response.Printf("cpusubtype:%" PRIx32 ";", cpu_subtype);
12300b57cec5SDimitry Andric 
12310b57cec5SDimitry Andric     const std::string vendor = proc_triple.getVendorName();
12320b57cec5SDimitry Andric     if (!vendor.empty())
12330b57cec5SDimitry Andric       response.Printf("vendor:%s;", vendor.c_str());
12340b57cec5SDimitry Andric #else
12350b57cec5SDimitry Andric     // We'll send the triple.
12360b57cec5SDimitry Andric     response.PutCString("triple:");
12370b57cec5SDimitry Andric     response.PutStringAsRawHex8(proc_triple.getTriple());
12380b57cec5SDimitry Andric     response.PutChar(';');
12390b57cec5SDimitry Andric #endif
12400b57cec5SDimitry Andric     std::string ostype = proc_triple.getOSName();
12410b57cec5SDimitry Andric     // Adjust so ostype reports ios for Apple/ARM and Apple/ARM64.
12420b57cec5SDimitry Andric     if (proc_triple.getVendor() == llvm::Triple::Apple) {
12430b57cec5SDimitry Andric       switch (proc_triple.getArch()) {
12440b57cec5SDimitry Andric       case llvm::Triple::arm:
12450b57cec5SDimitry Andric       case llvm::Triple::thumb:
12460b57cec5SDimitry Andric       case llvm::Triple::aarch64:
1247*9dba64beSDimitry Andric       case llvm::Triple::aarch64_32:
12480b57cec5SDimitry Andric         ostype = "ios";
12490b57cec5SDimitry Andric         break;
12500b57cec5SDimitry Andric       default:
12510b57cec5SDimitry Andric         // No change.
12520b57cec5SDimitry Andric         break;
12530b57cec5SDimitry Andric       }
12540b57cec5SDimitry Andric     }
12550b57cec5SDimitry Andric     response.Printf("ostype:%s;", ostype.c_str());
12560b57cec5SDimitry Andric 
12570b57cec5SDimitry Andric     switch (proc_arch.GetByteOrder()) {
12580b57cec5SDimitry Andric     case lldb::eByteOrderLittle:
12590b57cec5SDimitry Andric       response.PutCString("endian:little;");
12600b57cec5SDimitry Andric       break;
12610b57cec5SDimitry Andric     case lldb::eByteOrderBig:
12620b57cec5SDimitry Andric       response.PutCString("endian:big;");
12630b57cec5SDimitry Andric       break;
12640b57cec5SDimitry Andric     case lldb::eByteOrderPDP:
12650b57cec5SDimitry Andric       response.PutCString("endian:pdp;");
12660b57cec5SDimitry Andric       break;
12670b57cec5SDimitry Andric     default:
12680b57cec5SDimitry Andric       // Nothing.
12690b57cec5SDimitry Andric       break;
12700b57cec5SDimitry Andric     }
12710b57cec5SDimitry Andric     // In case of MIPS64, pointer size is depend on ELF ABI For N32 the pointer
12720b57cec5SDimitry Andric     // size is 4 and for N64 it is 8
12730b57cec5SDimitry Andric     std::string abi = proc_arch.GetTargetABI();
12740b57cec5SDimitry Andric     if (!abi.empty())
12750b57cec5SDimitry Andric       response.Printf("elf_abi:%s;", abi.c_str());
12760b57cec5SDimitry Andric     response.Printf("ptrsize:%d;", proc_arch.GetAddressByteSize());
12770b57cec5SDimitry Andric   }
12780b57cec5SDimitry Andric }
12790b57cec5SDimitry Andric 
12800b57cec5SDimitry Andric FileSpec GDBRemoteCommunicationServerCommon::FindModuleFile(
12810b57cec5SDimitry Andric     const std::string &module_path, const ArchSpec &arch) {
12820b57cec5SDimitry Andric #ifdef __ANDROID__
12830b57cec5SDimitry Andric   return HostInfoAndroid::ResolveLibraryPath(module_path, arch);
12840b57cec5SDimitry Andric #else
12850b57cec5SDimitry Andric   FileSpec file_spec(module_path);
12860b57cec5SDimitry Andric   FileSystem::Instance().Resolve(file_spec);
12870b57cec5SDimitry Andric   return file_spec;
12880b57cec5SDimitry Andric #endif
12890b57cec5SDimitry Andric }
12900b57cec5SDimitry Andric 
12910b57cec5SDimitry Andric ModuleSpec
12920b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::GetModuleInfo(llvm::StringRef module_path,
12930b57cec5SDimitry Andric                                                   llvm::StringRef triple) {
12940b57cec5SDimitry Andric   ArchSpec arch(triple);
12950b57cec5SDimitry Andric 
12960b57cec5SDimitry Andric   FileSpec req_module_path_spec(module_path);
12970b57cec5SDimitry Andric   FileSystem::Instance().Resolve(req_module_path_spec);
12980b57cec5SDimitry Andric 
12990b57cec5SDimitry Andric   const FileSpec module_path_spec =
13000b57cec5SDimitry Andric       FindModuleFile(req_module_path_spec.GetPath(), arch);
13010b57cec5SDimitry Andric   const ModuleSpec module_spec(module_path_spec, arch);
13020b57cec5SDimitry Andric 
13030b57cec5SDimitry Andric   ModuleSpecList module_specs;
13040b57cec5SDimitry Andric   if (!ObjectFile::GetModuleSpecifications(module_path_spec, 0, 0,
13050b57cec5SDimitry Andric                                            module_specs))
13060b57cec5SDimitry Andric     return ModuleSpec();
13070b57cec5SDimitry Andric 
13080b57cec5SDimitry Andric   ModuleSpec matched_module_spec;
13090b57cec5SDimitry Andric   if (!module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec))
13100b57cec5SDimitry Andric     return ModuleSpec();
13110b57cec5SDimitry Andric 
13120b57cec5SDimitry Andric   return matched_module_spec;
13130b57cec5SDimitry Andric }
1314