1*0b57cec5SDimitry Andric //===-- GDBRemoteCommunicationServerCommon.cpp ------------------*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "GDBRemoteCommunicationServerCommon.h" 10*0b57cec5SDimitry Andric 11*0b57cec5SDimitry Andric #include <errno.h> 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #ifdef __APPLE__ 14*0b57cec5SDimitry Andric #include <TargetConditionals.h> 15*0b57cec5SDimitry Andric #endif 16*0b57cec5SDimitry Andric 17*0b57cec5SDimitry Andric #include <chrono> 18*0b57cec5SDimitry Andric #include <cstring> 19*0b57cec5SDimitry Andric 20*0b57cec5SDimitry Andric #include "lldb/Core/ModuleSpec.h" 21*0b57cec5SDimitry Andric #include "lldb/Host/Config.h" 22*0b57cec5SDimitry Andric #include "lldb/Host/File.h" 23*0b57cec5SDimitry Andric #include "lldb/Host/FileAction.h" 24*0b57cec5SDimitry Andric #include "lldb/Host/FileSystem.h" 25*0b57cec5SDimitry Andric #include "lldb/Host/Host.h" 26*0b57cec5SDimitry Andric #include "lldb/Host/HostInfo.h" 27*0b57cec5SDimitry Andric #include "lldb/Host/SafeMachO.h" 28*0b57cec5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h" 29*0b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 30*0b57cec5SDimitry Andric #include "lldb/Target/Platform.h" 31*0b57cec5SDimitry Andric #include "lldb/Utility/Endian.h" 32*0b57cec5SDimitry Andric #include "lldb/Utility/JSON.h" 33*0b57cec5SDimitry Andric #include "lldb/Utility/Log.h" 34*0b57cec5SDimitry Andric #include "lldb/Utility/StreamGDBRemote.h" 35*0b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h" 36*0b57cec5SDimitry Andric #include "lldb/Utility/StructuredData.h" 37*0b57cec5SDimitry Andric #include "llvm/ADT/Triple.h" 38*0b57cec5SDimitry Andric 39*0b57cec5SDimitry Andric #include "ProcessGDBRemoteLog.h" 40*0b57cec5SDimitry Andric #include "lldb/Utility/StringExtractorGDBRemote.h" 41*0b57cec5SDimitry Andric 42*0b57cec5SDimitry Andric #ifdef __ANDROID__ 43*0b57cec5SDimitry Andric #include "lldb/Host/android/HostInfoAndroid.h" 44*0b57cec5SDimitry Andric #endif 45*0b57cec5SDimitry Andric 46*0b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h" 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric using namespace lldb; 49*0b57cec5SDimitry Andric using namespace lldb_private; 50*0b57cec5SDimitry Andric using namespace lldb_private::process_gdb_remote; 51*0b57cec5SDimitry Andric 52*0b57cec5SDimitry Andric #ifdef __ANDROID__ 53*0b57cec5SDimitry Andric const static uint32_t g_default_packet_timeout_sec = 20; // seconds 54*0b57cec5SDimitry Andric #else 55*0b57cec5SDimitry Andric const static uint32_t g_default_packet_timeout_sec = 0; // not specified 56*0b57cec5SDimitry Andric #endif 57*0b57cec5SDimitry Andric 58*0b57cec5SDimitry Andric // GDBRemoteCommunicationServerCommon constructor 59*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon( 60*0b57cec5SDimitry Andric const char *comm_name, const char *listener_name) 61*0b57cec5SDimitry Andric : GDBRemoteCommunicationServer(comm_name, listener_name), 62*0b57cec5SDimitry Andric m_process_launch_info(), m_process_launch_error(), m_proc_infos(), 63*0b57cec5SDimitry Andric m_proc_infos_index(0), m_thread_suffix_supported(false), 64*0b57cec5SDimitry Andric m_list_threads_in_stop_reply(false) { 65*0b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_A, 66*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_A); 67*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 68*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QEnvironment, 69*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_QEnvironment); 70*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 71*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QEnvironmentHexEncoded, 72*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded); 73*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 74*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qfProcessInfo, 75*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo); 76*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 77*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qGroupName, 78*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_qGroupName); 79*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 80*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qHostInfo, 81*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_qHostInfo); 82*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 83*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QLaunchArch, 84*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_QLaunchArch); 85*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 86*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess, 87*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess); 88*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 89*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply, 90*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply); 91*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 92*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qEcho, 93*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_qEcho); 94*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 95*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qModuleInfo, 96*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_qModuleInfo); 97*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 98*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_jModulesInfo, 99*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_jModulesInfo); 100*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 101*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod, 102*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod); 103*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 104*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir, 105*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir); 106*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 107*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qPlatform_shell, 108*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell); 109*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 110*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID, 111*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_qProcessInfoPID); 112*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 113*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QSetDetachOnError, 114*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError); 115*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 116*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QSetSTDERR, 117*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR); 118*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 119*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QSetSTDIN, 120*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN); 121*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 122*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT, 123*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT); 124*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 125*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qSpeedTest, 126*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_qSpeedTest); 127*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 128*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qsProcessInfo, 129*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo); 130*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 131*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode, 132*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode); 133*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 134*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qSupported, 135*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_qSupported); 136*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 137*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported, 138*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported); 139*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 140*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qUserName, 141*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_qUserName); 142*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 143*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vFile_close, 144*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_vFile_Close); 145*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 146*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vFile_exists, 147*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_vFile_Exists); 148*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 149*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vFile_md5, 150*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_vFile_MD5); 151*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 152*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vFile_mode, 153*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_vFile_Mode); 154*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 155*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vFile_open, 156*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_vFile_Open); 157*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 158*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vFile_pread, 159*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_vFile_pRead); 160*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 161*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vFile_pwrite, 162*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite); 163*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 164*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vFile_size, 165*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_vFile_Size); 166*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 167*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vFile_stat, 168*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_vFile_Stat); 169*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 170*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vFile_symlink, 171*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_vFile_symlink); 172*0b57cec5SDimitry Andric RegisterMemberFunctionHandler( 173*0b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vFile_unlink, 174*0b57cec5SDimitry Andric &GDBRemoteCommunicationServerCommon::Handle_vFile_unlink); 175*0b57cec5SDimitry Andric } 176*0b57cec5SDimitry Andric 177*0b57cec5SDimitry Andric // Destructor 178*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::~GDBRemoteCommunicationServerCommon() {} 179*0b57cec5SDimitry Andric 180*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 181*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qHostInfo( 182*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 183*0b57cec5SDimitry Andric StreamString response; 184*0b57cec5SDimitry Andric 185*0b57cec5SDimitry Andric // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00 186*0b57cec5SDimitry Andric 187*0b57cec5SDimitry Andric ArchSpec host_arch(HostInfo::GetArchitecture()); 188*0b57cec5SDimitry Andric const llvm::Triple &host_triple = host_arch.GetTriple(); 189*0b57cec5SDimitry Andric response.PutCString("triple:"); 190*0b57cec5SDimitry Andric response.PutStringAsRawHex8(host_triple.getTriple()); 191*0b57cec5SDimitry Andric response.Printf(";ptrsize:%u;", host_arch.GetAddressByteSize()); 192*0b57cec5SDimitry Andric 193*0b57cec5SDimitry Andric const char *distribution_id = host_arch.GetDistributionId().AsCString(); 194*0b57cec5SDimitry Andric if (distribution_id) { 195*0b57cec5SDimitry Andric response.PutCString("distribution_id:"); 196*0b57cec5SDimitry Andric response.PutStringAsRawHex8(distribution_id); 197*0b57cec5SDimitry Andric response.PutCString(";"); 198*0b57cec5SDimitry Andric } 199*0b57cec5SDimitry Andric 200*0b57cec5SDimitry Andric #if defined(__APPLE__) 201*0b57cec5SDimitry Andric // For parity with debugserver, we'll include the vendor key. 202*0b57cec5SDimitry Andric response.PutCString("vendor:apple;"); 203*0b57cec5SDimitry Andric 204*0b57cec5SDimitry Andric // Send out MachO info. 205*0b57cec5SDimitry Andric uint32_t cpu = host_arch.GetMachOCPUType(); 206*0b57cec5SDimitry Andric uint32_t sub = host_arch.GetMachOCPUSubType(); 207*0b57cec5SDimitry Andric if (cpu != LLDB_INVALID_CPUTYPE) 208*0b57cec5SDimitry Andric response.Printf("cputype:%u;", cpu); 209*0b57cec5SDimitry Andric if (sub != LLDB_INVALID_CPUTYPE) 210*0b57cec5SDimitry Andric response.Printf("cpusubtype:%u;", sub); 211*0b57cec5SDimitry Andric 212*0b57cec5SDimitry Andric if (cpu == llvm::MachO::CPU_TYPE_ARM || cpu == llvm::MachO::CPU_TYPE_ARM64) { 213*0b57cec5SDimitry Andric // Indicate the OS type. 214*0b57cec5SDimitry Andric #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1 215*0b57cec5SDimitry Andric response.PutCString("ostype:tvos;"); 216*0b57cec5SDimitry Andric #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 217*0b57cec5SDimitry Andric response.PutCString("ostype:watchos;"); 218*0b57cec5SDimitry Andric #elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1 219*0b57cec5SDimitry Andric response.PutCString("ostype:bridgeos;"); 220*0b57cec5SDimitry Andric #else 221*0b57cec5SDimitry Andric response.PutCString("ostype:ios;"); 222*0b57cec5SDimitry Andric #endif 223*0b57cec5SDimitry Andric 224*0b57cec5SDimitry Andric // On arm, we use "synchronous" watchpoints which means the exception is 225*0b57cec5SDimitry Andric // delivered before the instruction executes. 226*0b57cec5SDimitry Andric response.PutCString("watchpoint_exceptions_received:before;"); 227*0b57cec5SDimitry Andric } else { 228*0b57cec5SDimitry Andric response.PutCString("ostype:macosx;"); 229*0b57cec5SDimitry Andric response.Printf("watchpoint_exceptions_received:after;"); 230*0b57cec5SDimitry Andric } 231*0b57cec5SDimitry Andric 232*0b57cec5SDimitry Andric #else 233*0b57cec5SDimitry Andric if (host_arch.GetMachine() == llvm::Triple::aarch64 || 234*0b57cec5SDimitry Andric host_arch.GetMachine() == llvm::Triple::aarch64_be || 235*0b57cec5SDimitry Andric host_arch.GetMachine() == llvm::Triple::arm || 236*0b57cec5SDimitry Andric host_arch.GetMachine() == llvm::Triple::armeb || host_arch.IsMIPS()) 237*0b57cec5SDimitry Andric response.Printf("watchpoint_exceptions_received:before;"); 238*0b57cec5SDimitry Andric else 239*0b57cec5SDimitry Andric response.Printf("watchpoint_exceptions_received:after;"); 240*0b57cec5SDimitry Andric #endif 241*0b57cec5SDimitry Andric 242*0b57cec5SDimitry Andric switch (endian::InlHostByteOrder()) { 243*0b57cec5SDimitry Andric case eByteOrderBig: 244*0b57cec5SDimitry Andric response.PutCString("endian:big;"); 245*0b57cec5SDimitry Andric break; 246*0b57cec5SDimitry Andric case eByteOrderLittle: 247*0b57cec5SDimitry Andric response.PutCString("endian:little;"); 248*0b57cec5SDimitry Andric break; 249*0b57cec5SDimitry Andric case eByteOrderPDP: 250*0b57cec5SDimitry Andric response.PutCString("endian:pdp;"); 251*0b57cec5SDimitry Andric break; 252*0b57cec5SDimitry Andric default: 253*0b57cec5SDimitry Andric response.PutCString("endian:unknown;"); 254*0b57cec5SDimitry Andric break; 255*0b57cec5SDimitry Andric } 256*0b57cec5SDimitry Andric 257*0b57cec5SDimitry Andric llvm::VersionTuple version = HostInfo::GetOSVersion(); 258*0b57cec5SDimitry Andric if (!version.empty()) { 259*0b57cec5SDimitry Andric response.Format("os_version:{0}", version.getAsString()); 260*0b57cec5SDimitry Andric response.PutChar(';'); 261*0b57cec5SDimitry Andric } 262*0b57cec5SDimitry Andric 263*0b57cec5SDimitry Andric std::string s; 264*0b57cec5SDimitry Andric if (HostInfo::GetOSBuildString(s)) { 265*0b57cec5SDimitry Andric response.PutCString("os_build:"); 266*0b57cec5SDimitry Andric response.PutStringAsRawHex8(s); 267*0b57cec5SDimitry Andric response.PutChar(';'); 268*0b57cec5SDimitry Andric } 269*0b57cec5SDimitry Andric if (HostInfo::GetOSKernelDescription(s)) { 270*0b57cec5SDimitry Andric response.PutCString("os_kernel:"); 271*0b57cec5SDimitry Andric response.PutStringAsRawHex8(s); 272*0b57cec5SDimitry Andric response.PutChar(';'); 273*0b57cec5SDimitry Andric } 274*0b57cec5SDimitry Andric 275*0b57cec5SDimitry Andric #if defined(__APPLE__) 276*0b57cec5SDimitry Andric 277*0b57cec5SDimitry Andric #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) 278*0b57cec5SDimitry Andric // For iOS devices, we are connected through a USB Mux so we never pretend to 279*0b57cec5SDimitry Andric // actually have a hostname as far as the remote lldb that is connecting to 280*0b57cec5SDimitry Andric // this lldb-platform is concerned 281*0b57cec5SDimitry Andric response.PutCString("hostname:"); 282*0b57cec5SDimitry Andric response.PutStringAsRawHex8("127.0.0.1"); 283*0b57cec5SDimitry Andric response.PutChar(';'); 284*0b57cec5SDimitry Andric #else // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) 285*0b57cec5SDimitry Andric if (HostInfo::GetHostname(s)) { 286*0b57cec5SDimitry Andric response.PutCString("hostname:"); 287*0b57cec5SDimitry Andric response.PutStringAsRawHex8(s); 288*0b57cec5SDimitry Andric response.PutChar(';'); 289*0b57cec5SDimitry Andric } 290*0b57cec5SDimitry Andric #endif // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) 291*0b57cec5SDimitry Andric 292*0b57cec5SDimitry Andric #else // #if defined(__APPLE__) 293*0b57cec5SDimitry Andric if (HostInfo::GetHostname(s)) { 294*0b57cec5SDimitry Andric response.PutCString("hostname:"); 295*0b57cec5SDimitry Andric response.PutStringAsRawHex8(s); 296*0b57cec5SDimitry Andric response.PutChar(';'); 297*0b57cec5SDimitry Andric } 298*0b57cec5SDimitry Andric #endif // #if defined(__APPLE__) 299*0b57cec5SDimitry Andric 300*0b57cec5SDimitry Andric if (g_default_packet_timeout_sec > 0) 301*0b57cec5SDimitry Andric response.Printf("default_packet_timeout:%u;", g_default_packet_timeout_sec); 302*0b57cec5SDimitry Andric 303*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 304*0b57cec5SDimitry Andric } 305*0b57cec5SDimitry Andric 306*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 307*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qProcessInfoPID( 308*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 309*0b57cec5SDimitry Andric // Packet format: "qProcessInfoPID:%i" where %i is the pid 310*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("qProcessInfoPID:")); 311*0b57cec5SDimitry Andric lldb::pid_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID); 312*0b57cec5SDimitry Andric if (pid != LLDB_INVALID_PROCESS_ID) { 313*0b57cec5SDimitry Andric ProcessInstanceInfo proc_info; 314*0b57cec5SDimitry Andric if (Host::GetProcessInfo(pid, proc_info)) { 315*0b57cec5SDimitry Andric StreamString response; 316*0b57cec5SDimitry Andric CreateProcessInfoResponse(proc_info, response); 317*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 318*0b57cec5SDimitry Andric } 319*0b57cec5SDimitry Andric } 320*0b57cec5SDimitry Andric return SendErrorResponse(1); 321*0b57cec5SDimitry Andric } 322*0b57cec5SDimitry Andric 323*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 324*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo( 325*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 326*0b57cec5SDimitry Andric m_proc_infos_index = 0; 327*0b57cec5SDimitry Andric m_proc_infos.Clear(); 328*0b57cec5SDimitry Andric 329*0b57cec5SDimitry Andric ProcessInstanceInfoMatch match_info; 330*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("qfProcessInfo")); 331*0b57cec5SDimitry Andric if (packet.GetChar() == ':') { 332*0b57cec5SDimitry Andric llvm::StringRef key; 333*0b57cec5SDimitry Andric llvm::StringRef value; 334*0b57cec5SDimitry Andric while (packet.GetNameColonValue(key, value)) { 335*0b57cec5SDimitry Andric bool success = true; 336*0b57cec5SDimitry Andric if (key.equals("name")) { 337*0b57cec5SDimitry Andric StringExtractor extractor(value); 338*0b57cec5SDimitry Andric std::string file; 339*0b57cec5SDimitry Andric extractor.GetHexByteString(file); 340*0b57cec5SDimitry Andric match_info.GetProcessInfo().GetExecutableFile().SetFile( 341*0b57cec5SDimitry Andric file, FileSpec::Style::native); 342*0b57cec5SDimitry Andric } else if (key.equals("name_match")) { 343*0b57cec5SDimitry Andric NameMatch name_match = llvm::StringSwitch<NameMatch>(value) 344*0b57cec5SDimitry Andric .Case("equals", NameMatch::Equals) 345*0b57cec5SDimitry Andric .Case("starts_with", NameMatch::StartsWith) 346*0b57cec5SDimitry Andric .Case("ends_with", NameMatch::EndsWith) 347*0b57cec5SDimitry Andric .Case("contains", NameMatch::Contains) 348*0b57cec5SDimitry Andric .Case("regex", NameMatch::RegularExpression) 349*0b57cec5SDimitry Andric .Default(NameMatch::Ignore); 350*0b57cec5SDimitry Andric match_info.SetNameMatchType(name_match); 351*0b57cec5SDimitry Andric if (name_match == NameMatch::Ignore) 352*0b57cec5SDimitry Andric return SendErrorResponse(2); 353*0b57cec5SDimitry Andric } else if (key.equals("pid")) { 354*0b57cec5SDimitry Andric lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; 355*0b57cec5SDimitry Andric if (value.getAsInteger(0, pid)) 356*0b57cec5SDimitry Andric return SendErrorResponse(2); 357*0b57cec5SDimitry Andric match_info.GetProcessInfo().SetProcessID(pid); 358*0b57cec5SDimitry Andric } else if (key.equals("parent_pid")) { 359*0b57cec5SDimitry Andric lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; 360*0b57cec5SDimitry Andric if (value.getAsInteger(0, pid)) 361*0b57cec5SDimitry Andric return SendErrorResponse(2); 362*0b57cec5SDimitry Andric match_info.GetProcessInfo().SetParentProcessID(pid); 363*0b57cec5SDimitry Andric } else if (key.equals("uid")) { 364*0b57cec5SDimitry Andric uint32_t uid = UINT32_MAX; 365*0b57cec5SDimitry Andric if (value.getAsInteger(0, uid)) 366*0b57cec5SDimitry Andric return SendErrorResponse(2); 367*0b57cec5SDimitry Andric match_info.GetProcessInfo().SetUserID(uid); 368*0b57cec5SDimitry Andric } else if (key.equals("gid")) { 369*0b57cec5SDimitry Andric uint32_t gid = UINT32_MAX; 370*0b57cec5SDimitry Andric if (value.getAsInteger(0, gid)) 371*0b57cec5SDimitry Andric return SendErrorResponse(2); 372*0b57cec5SDimitry Andric match_info.GetProcessInfo().SetGroupID(gid); 373*0b57cec5SDimitry Andric } else if (key.equals("euid")) { 374*0b57cec5SDimitry Andric uint32_t uid = UINT32_MAX; 375*0b57cec5SDimitry Andric if (value.getAsInteger(0, uid)) 376*0b57cec5SDimitry Andric return SendErrorResponse(2); 377*0b57cec5SDimitry Andric match_info.GetProcessInfo().SetEffectiveUserID(uid); 378*0b57cec5SDimitry Andric } else if (key.equals("egid")) { 379*0b57cec5SDimitry Andric uint32_t gid = UINT32_MAX; 380*0b57cec5SDimitry Andric if (value.getAsInteger(0, gid)) 381*0b57cec5SDimitry Andric return SendErrorResponse(2); 382*0b57cec5SDimitry Andric match_info.GetProcessInfo().SetEffectiveGroupID(gid); 383*0b57cec5SDimitry Andric } else if (key.equals("all_users")) { 384*0b57cec5SDimitry Andric match_info.SetMatchAllUsers( 385*0b57cec5SDimitry Andric OptionArgParser::ToBoolean(value, false, &success)); 386*0b57cec5SDimitry Andric } else if (key.equals("triple")) { 387*0b57cec5SDimitry Andric match_info.GetProcessInfo().GetArchitecture() = 388*0b57cec5SDimitry Andric HostInfo::GetAugmentedArchSpec(value); 389*0b57cec5SDimitry Andric } else { 390*0b57cec5SDimitry Andric success = false; 391*0b57cec5SDimitry Andric } 392*0b57cec5SDimitry Andric 393*0b57cec5SDimitry Andric if (!success) 394*0b57cec5SDimitry Andric return SendErrorResponse(2); 395*0b57cec5SDimitry Andric } 396*0b57cec5SDimitry Andric } 397*0b57cec5SDimitry Andric 398*0b57cec5SDimitry Andric if (Host::FindProcesses(match_info, m_proc_infos)) { 399*0b57cec5SDimitry Andric // We found something, return the first item by calling the get subsequent 400*0b57cec5SDimitry Andric // process info packet handler... 401*0b57cec5SDimitry Andric return Handle_qsProcessInfo(packet); 402*0b57cec5SDimitry Andric } 403*0b57cec5SDimitry Andric return SendErrorResponse(3); 404*0b57cec5SDimitry Andric } 405*0b57cec5SDimitry Andric 406*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 407*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo( 408*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 409*0b57cec5SDimitry Andric if (m_proc_infos_index < m_proc_infos.GetSize()) { 410*0b57cec5SDimitry Andric StreamString response; 411*0b57cec5SDimitry Andric CreateProcessInfoResponse( 412*0b57cec5SDimitry Andric m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response); 413*0b57cec5SDimitry Andric ++m_proc_infos_index; 414*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 415*0b57cec5SDimitry Andric } 416*0b57cec5SDimitry Andric return SendErrorResponse(4); 417*0b57cec5SDimitry Andric } 418*0b57cec5SDimitry Andric 419*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 420*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qUserName( 421*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 422*0b57cec5SDimitry Andric #if !defined(LLDB_DISABLE_POSIX) 423*0b57cec5SDimitry Andric Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); 424*0b57cec5SDimitry Andric if (log) 425*0b57cec5SDimitry Andric log->Printf("GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__); 426*0b57cec5SDimitry Andric 427*0b57cec5SDimitry Andric // Packet format: "qUserName:%i" where %i is the uid 428*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("qUserName:")); 429*0b57cec5SDimitry Andric uint32_t uid = packet.GetU32(UINT32_MAX); 430*0b57cec5SDimitry Andric if (uid != UINT32_MAX) { 431*0b57cec5SDimitry Andric if (llvm::Optional<llvm::StringRef> name = 432*0b57cec5SDimitry Andric HostInfo::GetUserIDResolver().GetUserName(uid)) { 433*0b57cec5SDimitry Andric StreamString response; 434*0b57cec5SDimitry Andric response.PutStringAsRawHex8(*name); 435*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 436*0b57cec5SDimitry Andric } 437*0b57cec5SDimitry Andric } 438*0b57cec5SDimitry Andric if (log) 439*0b57cec5SDimitry Andric log->Printf("GDBRemoteCommunicationServerCommon::%s end", __FUNCTION__); 440*0b57cec5SDimitry Andric #endif 441*0b57cec5SDimitry Andric return SendErrorResponse(5); 442*0b57cec5SDimitry Andric } 443*0b57cec5SDimitry Andric 444*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 445*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qGroupName( 446*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 447*0b57cec5SDimitry Andric #if !defined(LLDB_DISABLE_POSIX) 448*0b57cec5SDimitry Andric // Packet format: "qGroupName:%i" where %i is the gid 449*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("qGroupName:")); 450*0b57cec5SDimitry Andric uint32_t gid = packet.GetU32(UINT32_MAX); 451*0b57cec5SDimitry Andric if (gid != UINT32_MAX) { 452*0b57cec5SDimitry Andric if (llvm::Optional<llvm::StringRef> name = 453*0b57cec5SDimitry Andric HostInfo::GetUserIDResolver().GetGroupName(gid)) { 454*0b57cec5SDimitry Andric StreamString response; 455*0b57cec5SDimitry Andric response.PutStringAsRawHex8(*name); 456*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 457*0b57cec5SDimitry Andric } 458*0b57cec5SDimitry Andric } 459*0b57cec5SDimitry Andric #endif 460*0b57cec5SDimitry Andric return SendErrorResponse(6); 461*0b57cec5SDimitry Andric } 462*0b57cec5SDimitry Andric 463*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 464*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qSpeedTest( 465*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 466*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("qSpeedTest:")); 467*0b57cec5SDimitry Andric 468*0b57cec5SDimitry Andric llvm::StringRef key; 469*0b57cec5SDimitry Andric llvm::StringRef value; 470*0b57cec5SDimitry Andric bool success = packet.GetNameColonValue(key, value); 471*0b57cec5SDimitry Andric if (success && key.equals("response_size")) { 472*0b57cec5SDimitry Andric uint32_t response_size = 0; 473*0b57cec5SDimitry Andric if (!value.getAsInteger(0, response_size)) { 474*0b57cec5SDimitry Andric if (response_size == 0) 475*0b57cec5SDimitry Andric return SendOKResponse(); 476*0b57cec5SDimitry Andric StreamString response; 477*0b57cec5SDimitry Andric uint32_t bytes_left = response_size; 478*0b57cec5SDimitry Andric response.PutCString("data:"); 479*0b57cec5SDimitry Andric while (bytes_left > 0) { 480*0b57cec5SDimitry Andric if (bytes_left >= 26) { 481*0b57cec5SDimitry Andric response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 482*0b57cec5SDimitry Andric bytes_left -= 26; 483*0b57cec5SDimitry Andric } else { 484*0b57cec5SDimitry Andric response.Printf("%*.*s;", bytes_left, bytes_left, 485*0b57cec5SDimitry Andric "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 486*0b57cec5SDimitry Andric bytes_left = 0; 487*0b57cec5SDimitry Andric } 488*0b57cec5SDimitry Andric } 489*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 490*0b57cec5SDimitry Andric } 491*0b57cec5SDimitry Andric } 492*0b57cec5SDimitry Andric return SendErrorResponse(7); 493*0b57cec5SDimitry Andric } 494*0b57cec5SDimitry Andric 495*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 496*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_Open( 497*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 498*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("vFile:open:")); 499*0b57cec5SDimitry Andric std::string path; 500*0b57cec5SDimitry Andric packet.GetHexByteStringTerminatedBy(path, ','); 501*0b57cec5SDimitry Andric if (!path.empty()) { 502*0b57cec5SDimitry Andric if (packet.GetChar() == ',') { 503*0b57cec5SDimitry Andric uint32_t flags = packet.GetHexMaxU32(false, 0); 504*0b57cec5SDimitry Andric if (packet.GetChar() == ',') { 505*0b57cec5SDimitry Andric mode_t mode = packet.GetHexMaxU32(false, 0600); 506*0b57cec5SDimitry Andric FileSpec path_spec(path); 507*0b57cec5SDimitry Andric FileSystem::Instance().Resolve(path_spec); 508*0b57cec5SDimitry Andric File file; 509*0b57cec5SDimitry Andric // Do not close fd. 510*0b57cec5SDimitry Andric Status error = 511*0b57cec5SDimitry Andric FileSystem::Instance().Open(file, path_spec, flags, mode, false); 512*0b57cec5SDimitry Andric const int save_errno = error.GetError(); 513*0b57cec5SDimitry Andric StreamString response; 514*0b57cec5SDimitry Andric response.PutChar('F'); 515*0b57cec5SDimitry Andric response.Printf("%i", file.GetDescriptor()); 516*0b57cec5SDimitry Andric if (save_errno) 517*0b57cec5SDimitry Andric response.Printf(",%i", save_errno); 518*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 519*0b57cec5SDimitry Andric } 520*0b57cec5SDimitry Andric } 521*0b57cec5SDimitry Andric } 522*0b57cec5SDimitry Andric return SendErrorResponse(18); 523*0b57cec5SDimitry Andric } 524*0b57cec5SDimitry Andric 525*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 526*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_Close( 527*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 528*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("vFile:close:")); 529*0b57cec5SDimitry Andric int fd = packet.GetS32(-1); 530*0b57cec5SDimitry Andric int err = -1; 531*0b57cec5SDimitry Andric int save_errno = 0; 532*0b57cec5SDimitry Andric if (fd >= 0) { 533*0b57cec5SDimitry Andric File file(fd, true); 534*0b57cec5SDimitry Andric Status error = file.Close(); 535*0b57cec5SDimitry Andric err = 0; 536*0b57cec5SDimitry Andric save_errno = error.GetError(); 537*0b57cec5SDimitry Andric } else { 538*0b57cec5SDimitry Andric save_errno = EINVAL; 539*0b57cec5SDimitry Andric } 540*0b57cec5SDimitry Andric StreamString response; 541*0b57cec5SDimitry Andric response.PutChar('F'); 542*0b57cec5SDimitry Andric response.Printf("%i", err); 543*0b57cec5SDimitry Andric if (save_errno) 544*0b57cec5SDimitry Andric response.Printf(",%i", save_errno); 545*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 546*0b57cec5SDimitry Andric } 547*0b57cec5SDimitry Andric 548*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 549*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_pRead( 550*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 551*0b57cec5SDimitry Andric StreamGDBRemote response; 552*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("vFile:pread:")); 553*0b57cec5SDimitry Andric int fd = packet.GetS32(-1); 554*0b57cec5SDimitry Andric if (packet.GetChar() == ',') { 555*0b57cec5SDimitry Andric size_t count = packet.GetU64(UINT64_MAX); 556*0b57cec5SDimitry Andric if (packet.GetChar() == ',') { 557*0b57cec5SDimitry Andric off_t offset = packet.GetU64(UINT32_MAX); 558*0b57cec5SDimitry Andric if (count == UINT64_MAX) { 559*0b57cec5SDimitry Andric response.Printf("F-1:%i", EINVAL); 560*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 561*0b57cec5SDimitry Andric } 562*0b57cec5SDimitry Andric 563*0b57cec5SDimitry Andric std::string buffer(count, 0); 564*0b57cec5SDimitry Andric File file(fd, false); 565*0b57cec5SDimitry Andric Status error = file.Read(static_cast<void *>(&buffer[0]), count, offset); 566*0b57cec5SDimitry Andric const ssize_t bytes_read = error.Success() ? count : -1; 567*0b57cec5SDimitry Andric const int save_errno = error.GetError(); 568*0b57cec5SDimitry Andric response.PutChar('F'); 569*0b57cec5SDimitry Andric response.Printf("%zi", bytes_read); 570*0b57cec5SDimitry Andric if (save_errno) 571*0b57cec5SDimitry Andric response.Printf(",%i", save_errno); 572*0b57cec5SDimitry Andric else { 573*0b57cec5SDimitry Andric response.PutChar(';'); 574*0b57cec5SDimitry Andric response.PutEscapedBytes(&buffer[0], bytes_read); 575*0b57cec5SDimitry Andric } 576*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 577*0b57cec5SDimitry Andric } 578*0b57cec5SDimitry Andric } 579*0b57cec5SDimitry Andric return SendErrorResponse(21); 580*0b57cec5SDimitry Andric } 581*0b57cec5SDimitry Andric 582*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 583*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite( 584*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 585*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("vFile:pwrite:")); 586*0b57cec5SDimitry Andric 587*0b57cec5SDimitry Andric StreamGDBRemote response; 588*0b57cec5SDimitry Andric response.PutChar('F'); 589*0b57cec5SDimitry Andric 590*0b57cec5SDimitry Andric int fd = packet.GetU32(UINT32_MAX); 591*0b57cec5SDimitry Andric if (packet.GetChar() == ',') { 592*0b57cec5SDimitry Andric off_t offset = packet.GetU64(UINT32_MAX); 593*0b57cec5SDimitry Andric if (packet.GetChar() == ',') { 594*0b57cec5SDimitry Andric std::string buffer; 595*0b57cec5SDimitry Andric if (packet.GetEscapedBinaryData(buffer)) { 596*0b57cec5SDimitry Andric File file(fd, false); 597*0b57cec5SDimitry Andric size_t count = buffer.size(); 598*0b57cec5SDimitry Andric Status error = 599*0b57cec5SDimitry Andric file.Write(static_cast<const void *>(&buffer[0]), count, offset); 600*0b57cec5SDimitry Andric const ssize_t bytes_written = error.Success() ? count : -1; 601*0b57cec5SDimitry Andric const int save_errno = error.GetError(); 602*0b57cec5SDimitry Andric response.Printf("%zi", bytes_written); 603*0b57cec5SDimitry Andric if (save_errno) 604*0b57cec5SDimitry Andric response.Printf(",%i", save_errno); 605*0b57cec5SDimitry Andric } else { 606*0b57cec5SDimitry Andric response.Printf("-1,%i", EINVAL); 607*0b57cec5SDimitry Andric } 608*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 609*0b57cec5SDimitry Andric } 610*0b57cec5SDimitry Andric } 611*0b57cec5SDimitry Andric return SendErrorResponse(27); 612*0b57cec5SDimitry Andric } 613*0b57cec5SDimitry Andric 614*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 615*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_Size( 616*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 617*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("vFile:size:")); 618*0b57cec5SDimitry Andric std::string path; 619*0b57cec5SDimitry Andric packet.GetHexByteString(path); 620*0b57cec5SDimitry Andric if (!path.empty()) { 621*0b57cec5SDimitry Andric uint64_t Size; 622*0b57cec5SDimitry Andric if (llvm::sys::fs::file_size(path, Size)) 623*0b57cec5SDimitry Andric return SendErrorResponse(5); 624*0b57cec5SDimitry Andric StreamString response; 625*0b57cec5SDimitry Andric response.PutChar('F'); 626*0b57cec5SDimitry Andric response.PutHex64(Size); 627*0b57cec5SDimitry Andric if (Size == UINT64_MAX) { 628*0b57cec5SDimitry Andric response.PutChar(','); 629*0b57cec5SDimitry Andric response.PutHex64(Size); // TODO: replace with Host::GetSyswideErrorCode() 630*0b57cec5SDimitry Andric } 631*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 632*0b57cec5SDimitry Andric } 633*0b57cec5SDimitry Andric return SendErrorResponse(22); 634*0b57cec5SDimitry Andric } 635*0b57cec5SDimitry Andric 636*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 637*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_Mode( 638*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 639*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("vFile:mode:")); 640*0b57cec5SDimitry Andric std::string path; 641*0b57cec5SDimitry Andric packet.GetHexByteString(path); 642*0b57cec5SDimitry Andric if (!path.empty()) { 643*0b57cec5SDimitry Andric FileSpec file_spec(path); 644*0b57cec5SDimitry Andric FileSystem::Instance().Resolve(file_spec); 645*0b57cec5SDimitry Andric std::error_code ec; 646*0b57cec5SDimitry Andric const uint32_t mode = FileSystem::Instance().GetPermissions(file_spec, ec); 647*0b57cec5SDimitry Andric StreamString response; 648*0b57cec5SDimitry Andric response.Printf("F%u", mode); 649*0b57cec5SDimitry Andric if (mode == 0 || ec) 650*0b57cec5SDimitry Andric response.Printf(",%i", (int)Status(ec).GetError()); 651*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 652*0b57cec5SDimitry Andric } 653*0b57cec5SDimitry Andric return SendErrorResponse(23); 654*0b57cec5SDimitry Andric } 655*0b57cec5SDimitry Andric 656*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 657*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_Exists( 658*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 659*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("vFile:exists:")); 660*0b57cec5SDimitry Andric std::string path; 661*0b57cec5SDimitry Andric packet.GetHexByteString(path); 662*0b57cec5SDimitry Andric if (!path.empty()) { 663*0b57cec5SDimitry Andric bool retcode = llvm::sys::fs::exists(path); 664*0b57cec5SDimitry Andric StreamString response; 665*0b57cec5SDimitry Andric response.PutChar('F'); 666*0b57cec5SDimitry Andric response.PutChar(','); 667*0b57cec5SDimitry Andric if (retcode) 668*0b57cec5SDimitry Andric response.PutChar('1'); 669*0b57cec5SDimitry Andric else 670*0b57cec5SDimitry Andric response.PutChar('0'); 671*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 672*0b57cec5SDimitry Andric } 673*0b57cec5SDimitry Andric return SendErrorResponse(24); 674*0b57cec5SDimitry Andric } 675*0b57cec5SDimitry Andric 676*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 677*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_symlink( 678*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 679*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("vFile:symlink:")); 680*0b57cec5SDimitry Andric std::string dst, src; 681*0b57cec5SDimitry Andric packet.GetHexByteStringTerminatedBy(dst, ','); 682*0b57cec5SDimitry Andric packet.GetChar(); // Skip ',' char 683*0b57cec5SDimitry Andric packet.GetHexByteString(src); 684*0b57cec5SDimitry Andric 685*0b57cec5SDimitry Andric FileSpec src_spec(src); 686*0b57cec5SDimitry Andric FileSystem::Instance().Resolve(src_spec); 687*0b57cec5SDimitry Andric Status error = FileSystem::Instance().Symlink(src_spec, FileSpec(dst)); 688*0b57cec5SDimitry Andric 689*0b57cec5SDimitry Andric StreamString response; 690*0b57cec5SDimitry Andric response.Printf("F%u,%u", error.GetError(), error.GetError()); 691*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 692*0b57cec5SDimitry Andric } 693*0b57cec5SDimitry Andric 694*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 695*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_unlink( 696*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 697*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("vFile:unlink:")); 698*0b57cec5SDimitry Andric std::string path; 699*0b57cec5SDimitry Andric packet.GetHexByteString(path); 700*0b57cec5SDimitry Andric Status error(llvm::sys::fs::remove(path)); 701*0b57cec5SDimitry Andric StreamString response; 702*0b57cec5SDimitry Andric response.Printf("F%u,%u", error.GetError(), error.GetError()); 703*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 704*0b57cec5SDimitry Andric } 705*0b57cec5SDimitry Andric 706*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 707*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell( 708*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 709*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("qPlatform_shell:")); 710*0b57cec5SDimitry Andric std::string path; 711*0b57cec5SDimitry Andric std::string working_dir; 712*0b57cec5SDimitry Andric packet.GetHexByteStringTerminatedBy(path, ','); 713*0b57cec5SDimitry Andric if (!path.empty()) { 714*0b57cec5SDimitry Andric if (packet.GetChar() == ',') { 715*0b57cec5SDimitry Andric // FIXME: add timeout to qPlatform_shell packet 716*0b57cec5SDimitry Andric // uint32_t timeout = packet.GetHexMaxU32(false, 32); 717*0b57cec5SDimitry Andric if (packet.GetChar() == ',') 718*0b57cec5SDimitry Andric packet.GetHexByteString(working_dir); 719*0b57cec5SDimitry Andric int status, signo; 720*0b57cec5SDimitry Andric std::string output; 721*0b57cec5SDimitry Andric FileSpec working_spec(working_dir); 722*0b57cec5SDimitry Andric FileSystem::Instance().Resolve(working_spec); 723*0b57cec5SDimitry Andric Status err = 724*0b57cec5SDimitry Andric Host::RunShellCommand(path.c_str(), working_spec, &status, &signo, 725*0b57cec5SDimitry Andric &output, std::chrono::seconds(10)); 726*0b57cec5SDimitry Andric StreamGDBRemote response; 727*0b57cec5SDimitry Andric if (err.Fail()) { 728*0b57cec5SDimitry Andric response.PutCString("F,"); 729*0b57cec5SDimitry Andric response.PutHex32(UINT32_MAX); 730*0b57cec5SDimitry Andric } else { 731*0b57cec5SDimitry Andric response.PutCString("F,"); 732*0b57cec5SDimitry Andric response.PutHex32(status); 733*0b57cec5SDimitry Andric response.PutChar(','); 734*0b57cec5SDimitry Andric response.PutHex32(signo); 735*0b57cec5SDimitry Andric response.PutChar(','); 736*0b57cec5SDimitry Andric response.PutEscapedBytes(output.c_str(), output.size()); 737*0b57cec5SDimitry Andric } 738*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 739*0b57cec5SDimitry Andric } 740*0b57cec5SDimitry Andric } 741*0b57cec5SDimitry Andric return SendErrorResponse(24); 742*0b57cec5SDimitry Andric } 743*0b57cec5SDimitry Andric 744*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 745*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_Stat( 746*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 747*0b57cec5SDimitry Andric return SendUnimplementedResponse( 748*0b57cec5SDimitry Andric "GDBRemoteCommunicationServerCommon::Handle_vFile_Stat() unimplemented"); 749*0b57cec5SDimitry Andric } 750*0b57cec5SDimitry Andric 751*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 752*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_vFile_MD5( 753*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 754*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("vFile:MD5:")); 755*0b57cec5SDimitry Andric std::string path; 756*0b57cec5SDimitry Andric packet.GetHexByteString(path); 757*0b57cec5SDimitry Andric if (!path.empty()) { 758*0b57cec5SDimitry Andric StreamGDBRemote response; 759*0b57cec5SDimitry Andric auto Result = llvm::sys::fs::md5_contents(path); 760*0b57cec5SDimitry Andric if (!Result) { 761*0b57cec5SDimitry Andric response.PutCString("F,"); 762*0b57cec5SDimitry Andric response.PutCString("x"); 763*0b57cec5SDimitry Andric } else { 764*0b57cec5SDimitry Andric response.PutCString("F,"); 765*0b57cec5SDimitry Andric response.PutHex64(Result->low()); 766*0b57cec5SDimitry Andric response.PutHex64(Result->high()); 767*0b57cec5SDimitry Andric } 768*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 769*0b57cec5SDimitry Andric } 770*0b57cec5SDimitry Andric return SendErrorResponse(25); 771*0b57cec5SDimitry Andric } 772*0b57cec5SDimitry Andric 773*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 774*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir( 775*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 776*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("qPlatform_mkdir:")); 777*0b57cec5SDimitry Andric mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX); 778*0b57cec5SDimitry Andric if (packet.GetChar() == ',') { 779*0b57cec5SDimitry Andric std::string path; 780*0b57cec5SDimitry Andric packet.GetHexByteString(path); 781*0b57cec5SDimitry Andric Status error(llvm::sys::fs::create_directory(path, mode)); 782*0b57cec5SDimitry Andric 783*0b57cec5SDimitry Andric StreamGDBRemote response; 784*0b57cec5SDimitry Andric response.Printf("F%u", error.GetError()); 785*0b57cec5SDimitry Andric 786*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 787*0b57cec5SDimitry Andric } 788*0b57cec5SDimitry Andric return SendErrorResponse(20); 789*0b57cec5SDimitry Andric } 790*0b57cec5SDimitry Andric 791*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 792*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod( 793*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 794*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("qPlatform_chmod:")); 795*0b57cec5SDimitry Andric 796*0b57cec5SDimitry Andric auto perms = 797*0b57cec5SDimitry Andric static_cast<llvm::sys::fs::perms>(packet.GetHexMaxU32(false, UINT32_MAX)); 798*0b57cec5SDimitry Andric if (packet.GetChar() == ',') { 799*0b57cec5SDimitry Andric std::string path; 800*0b57cec5SDimitry Andric packet.GetHexByteString(path); 801*0b57cec5SDimitry Andric Status error(llvm::sys::fs::setPermissions(path, perms)); 802*0b57cec5SDimitry Andric 803*0b57cec5SDimitry Andric StreamGDBRemote response; 804*0b57cec5SDimitry Andric response.Printf("F%u", error.GetError()); 805*0b57cec5SDimitry Andric 806*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 807*0b57cec5SDimitry Andric } 808*0b57cec5SDimitry Andric return SendErrorResponse(19); 809*0b57cec5SDimitry Andric } 810*0b57cec5SDimitry Andric 811*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 812*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qSupported( 813*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 814*0b57cec5SDimitry Andric StreamGDBRemote response; 815*0b57cec5SDimitry Andric 816*0b57cec5SDimitry Andric // Features common to lldb-platform and llgs. 817*0b57cec5SDimitry Andric uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet 818*0b57cec5SDimitry Andric // size--debugger can always use less 819*0b57cec5SDimitry Andric response.Printf("PacketSize=%x", max_packet_size); 820*0b57cec5SDimitry Andric 821*0b57cec5SDimitry Andric response.PutCString(";QStartNoAckMode+"); 822*0b57cec5SDimitry Andric response.PutCString(";QThreadSuffixSupported+"); 823*0b57cec5SDimitry Andric response.PutCString(";QListThreadsInStopReply+"); 824*0b57cec5SDimitry Andric response.PutCString(";qEcho+"); 825*0b57cec5SDimitry Andric #if defined(__linux__) || defined(__NetBSD__) 826*0b57cec5SDimitry Andric response.PutCString(";QPassSignals+"); 827*0b57cec5SDimitry Andric response.PutCString(";qXfer:auxv:read+"); 828*0b57cec5SDimitry Andric #endif 829*0b57cec5SDimitry Andric 830*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 831*0b57cec5SDimitry Andric } 832*0b57cec5SDimitry Andric 833*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 834*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported( 835*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 836*0b57cec5SDimitry Andric m_thread_suffix_supported = true; 837*0b57cec5SDimitry Andric return SendOKResponse(); 838*0b57cec5SDimitry Andric } 839*0b57cec5SDimitry Andric 840*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 841*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply( 842*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 843*0b57cec5SDimitry Andric m_list_threads_in_stop_reply = true; 844*0b57cec5SDimitry Andric return SendOKResponse(); 845*0b57cec5SDimitry Andric } 846*0b57cec5SDimitry Andric 847*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 848*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError( 849*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 850*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("QSetDetachOnError:")); 851*0b57cec5SDimitry Andric if (packet.GetU32(0)) 852*0b57cec5SDimitry Andric m_process_launch_info.GetFlags().Set(eLaunchFlagDetachOnError); 853*0b57cec5SDimitry Andric else 854*0b57cec5SDimitry Andric m_process_launch_info.GetFlags().Clear(eLaunchFlagDetachOnError); 855*0b57cec5SDimitry Andric return SendOKResponse(); 856*0b57cec5SDimitry Andric } 857*0b57cec5SDimitry Andric 858*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 859*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode( 860*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 861*0b57cec5SDimitry Andric // Send response first before changing m_send_acks to we ack this packet 862*0b57cec5SDimitry Andric PacketResult packet_result = SendOKResponse(); 863*0b57cec5SDimitry Andric m_send_acks = false; 864*0b57cec5SDimitry Andric return packet_result; 865*0b57cec5SDimitry Andric } 866*0b57cec5SDimitry Andric 867*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 868*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN( 869*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 870*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("QSetSTDIN:")); 871*0b57cec5SDimitry Andric FileAction file_action; 872*0b57cec5SDimitry Andric std::string path; 873*0b57cec5SDimitry Andric packet.GetHexByteString(path); 874*0b57cec5SDimitry Andric const bool read = true; 875*0b57cec5SDimitry Andric const bool write = false; 876*0b57cec5SDimitry Andric if (file_action.Open(STDIN_FILENO, FileSpec(path), read, write)) { 877*0b57cec5SDimitry Andric m_process_launch_info.AppendFileAction(file_action); 878*0b57cec5SDimitry Andric return SendOKResponse(); 879*0b57cec5SDimitry Andric } 880*0b57cec5SDimitry Andric return SendErrorResponse(15); 881*0b57cec5SDimitry Andric } 882*0b57cec5SDimitry Andric 883*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 884*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT( 885*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 886*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("QSetSTDOUT:")); 887*0b57cec5SDimitry Andric FileAction file_action; 888*0b57cec5SDimitry Andric std::string path; 889*0b57cec5SDimitry Andric packet.GetHexByteString(path); 890*0b57cec5SDimitry Andric const bool read = false; 891*0b57cec5SDimitry Andric const bool write = true; 892*0b57cec5SDimitry Andric if (file_action.Open(STDOUT_FILENO, FileSpec(path), read, write)) { 893*0b57cec5SDimitry Andric m_process_launch_info.AppendFileAction(file_action); 894*0b57cec5SDimitry Andric return SendOKResponse(); 895*0b57cec5SDimitry Andric } 896*0b57cec5SDimitry Andric return SendErrorResponse(16); 897*0b57cec5SDimitry Andric } 898*0b57cec5SDimitry Andric 899*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 900*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR( 901*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 902*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("QSetSTDERR:")); 903*0b57cec5SDimitry Andric FileAction file_action; 904*0b57cec5SDimitry Andric std::string path; 905*0b57cec5SDimitry Andric packet.GetHexByteString(path); 906*0b57cec5SDimitry Andric const bool read = false; 907*0b57cec5SDimitry Andric const bool write = true; 908*0b57cec5SDimitry Andric if (file_action.Open(STDERR_FILENO, FileSpec(path), read, write)) { 909*0b57cec5SDimitry Andric m_process_launch_info.AppendFileAction(file_action); 910*0b57cec5SDimitry Andric return SendOKResponse(); 911*0b57cec5SDimitry Andric } 912*0b57cec5SDimitry Andric return SendErrorResponse(17); 913*0b57cec5SDimitry Andric } 914*0b57cec5SDimitry Andric 915*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 916*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess( 917*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 918*0b57cec5SDimitry Andric if (m_process_launch_error.Success()) 919*0b57cec5SDimitry Andric return SendOKResponse(); 920*0b57cec5SDimitry Andric StreamString response; 921*0b57cec5SDimitry Andric response.PutChar('E'); 922*0b57cec5SDimitry Andric response.PutCString(m_process_launch_error.AsCString("<unknown error>")); 923*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 924*0b57cec5SDimitry Andric } 925*0b57cec5SDimitry Andric 926*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 927*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QEnvironment( 928*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 929*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("QEnvironment:")); 930*0b57cec5SDimitry Andric const uint32_t bytes_left = packet.GetBytesLeft(); 931*0b57cec5SDimitry Andric if (bytes_left > 0) { 932*0b57cec5SDimitry Andric m_process_launch_info.GetEnvironment().insert(packet.Peek()); 933*0b57cec5SDimitry Andric return SendOKResponse(); 934*0b57cec5SDimitry Andric } 935*0b57cec5SDimitry Andric return SendErrorResponse(12); 936*0b57cec5SDimitry Andric } 937*0b57cec5SDimitry Andric 938*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 939*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded( 940*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 941*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("QEnvironmentHexEncoded:")); 942*0b57cec5SDimitry Andric const uint32_t bytes_left = packet.GetBytesLeft(); 943*0b57cec5SDimitry Andric if (bytes_left > 0) { 944*0b57cec5SDimitry Andric std::string str; 945*0b57cec5SDimitry Andric packet.GetHexByteString(str); 946*0b57cec5SDimitry Andric m_process_launch_info.GetEnvironment().insert(str); 947*0b57cec5SDimitry Andric return SendOKResponse(); 948*0b57cec5SDimitry Andric } 949*0b57cec5SDimitry Andric return SendErrorResponse(12); 950*0b57cec5SDimitry Andric } 951*0b57cec5SDimitry Andric 952*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 953*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_QLaunchArch( 954*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 955*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("QLaunchArch:")); 956*0b57cec5SDimitry Andric const uint32_t bytes_left = packet.GetBytesLeft(); 957*0b57cec5SDimitry Andric if (bytes_left > 0) { 958*0b57cec5SDimitry Andric const char *arch_triple = packet.Peek(); 959*0b57cec5SDimitry Andric m_process_launch_info.SetArchitecture( 960*0b57cec5SDimitry Andric HostInfo::GetAugmentedArchSpec(arch_triple)); 961*0b57cec5SDimitry Andric return SendOKResponse(); 962*0b57cec5SDimitry Andric } 963*0b57cec5SDimitry Andric return SendErrorResponse(13); 964*0b57cec5SDimitry Andric } 965*0b57cec5SDimitry Andric 966*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 967*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) { 968*0b57cec5SDimitry Andric // The 'A' packet is the most over designed packet ever here with redundant 969*0b57cec5SDimitry Andric // argument indexes, redundant argument lengths and needed hex encoded 970*0b57cec5SDimitry Andric // argument string values. Really all that is needed is a comma separated hex 971*0b57cec5SDimitry Andric // encoded argument value list, but we will stay true to the documented 972*0b57cec5SDimitry Andric // version of the 'A' packet here... 973*0b57cec5SDimitry Andric 974*0b57cec5SDimitry Andric Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); 975*0b57cec5SDimitry Andric int actual_arg_index = 0; 976*0b57cec5SDimitry Andric 977*0b57cec5SDimitry Andric packet.SetFilePos(1); // Skip the 'A' 978*0b57cec5SDimitry Andric bool success = true; 979*0b57cec5SDimitry Andric while (success && packet.GetBytesLeft() > 0) { 980*0b57cec5SDimitry Andric // Decode the decimal argument string length. This length is the number of 981*0b57cec5SDimitry Andric // hex nibbles in the argument string value. 982*0b57cec5SDimitry Andric const uint32_t arg_len = packet.GetU32(UINT32_MAX); 983*0b57cec5SDimitry Andric if (arg_len == UINT32_MAX) 984*0b57cec5SDimitry Andric success = false; 985*0b57cec5SDimitry Andric else { 986*0b57cec5SDimitry Andric // Make sure the argument hex string length is followed by a comma 987*0b57cec5SDimitry Andric if (packet.GetChar() != ',') 988*0b57cec5SDimitry Andric success = false; 989*0b57cec5SDimitry Andric else { 990*0b57cec5SDimitry Andric // Decode the argument index. We ignore this really because who would 991*0b57cec5SDimitry Andric // really send down the arguments in a random order??? 992*0b57cec5SDimitry Andric const uint32_t arg_idx = packet.GetU32(UINT32_MAX); 993*0b57cec5SDimitry Andric if (arg_idx == UINT32_MAX) 994*0b57cec5SDimitry Andric success = false; 995*0b57cec5SDimitry Andric else { 996*0b57cec5SDimitry Andric // Make sure the argument index is followed by a comma 997*0b57cec5SDimitry Andric if (packet.GetChar() != ',') 998*0b57cec5SDimitry Andric success = false; 999*0b57cec5SDimitry Andric else { 1000*0b57cec5SDimitry Andric // Decode the argument string value from hex bytes back into a UTF8 1001*0b57cec5SDimitry Andric // string and make sure the length matches the one supplied in the 1002*0b57cec5SDimitry Andric // packet 1003*0b57cec5SDimitry Andric std::string arg; 1004*0b57cec5SDimitry Andric if (packet.GetHexByteStringFixedLength(arg, arg_len) != 1005*0b57cec5SDimitry Andric (arg_len / 2)) 1006*0b57cec5SDimitry Andric success = false; 1007*0b57cec5SDimitry Andric else { 1008*0b57cec5SDimitry Andric // If there are any bytes left 1009*0b57cec5SDimitry Andric if (packet.GetBytesLeft()) { 1010*0b57cec5SDimitry Andric if (packet.GetChar() != ',') 1011*0b57cec5SDimitry Andric success = false; 1012*0b57cec5SDimitry Andric } 1013*0b57cec5SDimitry Andric 1014*0b57cec5SDimitry Andric if (success) { 1015*0b57cec5SDimitry Andric if (arg_idx == 0) 1016*0b57cec5SDimitry Andric m_process_launch_info.GetExecutableFile().SetFile( 1017*0b57cec5SDimitry Andric arg, FileSpec::Style::native); 1018*0b57cec5SDimitry Andric m_process_launch_info.GetArguments().AppendArgument(arg); 1019*0b57cec5SDimitry Andric if (log) 1020*0b57cec5SDimitry Andric log->Printf("LLGSPacketHandler::%s added arg %d: \"%s\"", 1021*0b57cec5SDimitry Andric __FUNCTION__, actual_arg_index, arg.c_str()); 1022*0b57cec5SDimitry Andric ++actual_arg_index; 1023*0b57cec5SDimitry Andric } 1024*0b57cec5SDimitry Andric } 1025*0b57cec5SDimitry Andric } 1026*0b57cec5SDimitry Andric } 1027*0b57cec5SDimitry Andric } 1028*0b57cec5SDimitry Andric } 1029*0b57cec5SDimitry Andric } 1030*0b57cec5SDimitry Andric 1031*0b57cec5SDimitry Andric if (success) { 1032*0b57cec5SDimitry Andric m_process_launch_error = LaunchProcess(); 1033*0b57cec5SDimitry Andric if (m_process_launch_error.Success()) 1034*0b57cec5SDimitry Andric return SendOKResponse(); 1035*0b57cec5SDimitry Andric LLDB_LOG(log, "failed to launch exe: {0}", m_process_launch_error); 1036*0b57cec5SDimitry Andric } 1037*0b57cec5SDimitry Andric return SendErrorResponse(8); 1038*0b57cec5SDimitry Andric } 1039*0b57cec5SDimitry Andric 1040*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 1041*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qEcho( 1042*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 1043*0b57cec5SDimitry Andric // Just echo back the exact same packet for qEcho... 1044*0b57cec5SDimitry Andric return SendPacketNoLock(packet.GetStringRef()); 1045*0b57cec5SDimitry Andric } 1046*0b57cec5SDimitry Andric 1047*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 1048*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_qModuleInfo( 1049*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 1050*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("qModuleInfo:")); 1051*0b57cec5SDimitry Andric 1052*0b57cec5SDimitry Andric std::string module_path; 1053*0b57cec5SDimitry Andric packet.GetHexByteStringTerminatedBy(module_path, ';'); 1054*0b57cec5SDimitry Andric if (module_path.empty()) 1055*0b57cec5SDimitry Andric return SendErrorResponse(1); 1056*0b57cec5SDimitry Andric 1057*0b57cec5SDimitry Andric if (packet.GetChar() != ';') 1058*0b57cec5SDimitry Andric return SendErrorResponse(2); 1059*0b57cec5SDimitry Andric 1060*0b57cec5SDimitry Andric std::string triple; 1061*0b57cec5SDimitry Andric packet.GetHexByteString(triple); 1062*0b57cec5SDimitry Andric 1063*0b57cec5SDimitry Andric ModuleSpec matched_module_spec = GetModuleInfo(module_path, triple); 1064*0b57cec5SDimitry Andric if (!matched_module_spec.GetFileSpec()) 1065*0b57cec5SDimitry Andric return SendErrorResponse(3); 1066*0b57cec5SDimitry Andric 1067*0b57cec5SDimitry Andric const auto file_offset = matched_module_spec.GetObjectOffset(); 1068*0b57cec5SDimitry Andric const auto file_size = matched_module_spec.GetObjectSize(); 1069*0b57cec5SDimitry Andric const auto uuid_str = matched_module_spec.GetUUID().GetAsString(""); 1070*0b57cec5SDimitry Andric 1071*0b57cec5SDimitry Andric StreamGDBRemote response; 1072*0b57cec5SDimitry Andric 1073*0b57cec5SDimitry Andric if (uuid_str.empty()) { 1074*0b57cec5SDimitry Andric auto Result = llvm::sys::fs::md5_contents( 1075*0b57cec5SDimitry Andric matched_module_spec.GetFileSpec().GetPath()); 1076*0b57cec5SDimitry Andric if (!Result) 1077*0b57cec5SDimitry Andric return SendErrorResponse(5); 1078*0b57cec5SDimitry Andric response.PutCString("md5:"); 1079*0b57cec5SDimitry Andric response.PutStringAsRawHex8(Result->digest()); 1080*0b57cec5SDimitry Andric } else { 1081*0b57cec5SDimitry Andric response.PutCString("uuid:"); 1082*0b57cec5SDimitry Andric response.PutStringAsRawHex8(uuid_str); 1083*0b57cec5SDimitry Andric } 1084*0b57cec5SDimitry Andric response.PutChar(';'); 1085*0b57cec5SDimitry Andric 1086*0b57cec5SDimitry Andric const auto &module_arch = matched_module_spec.GetArchitecture(); 1087*0b57cec5SDimitry Andric response.PutCString("triple:"); 1088*0b57cec5SDimitry Andric response.PutStringAsRawHex8(module_arch.GetTriple().getTriple()); 1089*0b57cec5SDimitry Andric response.PutChar(';'); 1090*0b57cec5SDimitry Andric 1091*0b57cec5SDimitry Andric response.PutCString("file_path:"); 1092*0b57cec5SDimitry Andric response.PutStringAsRawHex8(matched_module_spec.GetFileSpec().GetCString()); 1093*0b57cec5SDimitry Andric response.PutChar(';'); 1094*0b57cec5SDimitry Andric response.PutCString("file_offset:"); 1095*0b57cec5SDimitry Andric response.PutHex64(file_offset); 1096*0b57cec5SDimitry Andric response.PutChar(';'); 1097*0b57cec5SDimitry Andric response.PutCString("file_size:"); 1098*0b57cec5SDimitry Andric response.PutHex64(file_size); 1099*0b57cec5SDimitry Andric response.PutChar(';'); 1100*0b57cec5SDimitry Andric 1101*0b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 1102*0b57cec5SDimitry Andric } 1103*0b57cec5SDimitry Andric 1104*0b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 1105*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::Handle_jModulesInfo( 1106*0b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 1107*0b57cec5SDimitry Andric packet.SetFilePos(::strlen("jModulesInfo:")); 1108*0b57cec5SDimitry Andric 1109*0b57cec5SDimitry Andric StructuredData::ObjectSP object_sp = StructuredData::ParseJSON(packet.Peek()); 1110*0b57cec5SDimitry Andric if (!object_sp) 1111*0b57cec5SDimitry Andric return SendErrorResponse(1); 1112*0b57cec5SDimitry Andric 1113*0b57cec5SDimitry Andric StructuredData::Array *packet_array = object_sp->GetAsArray(); 1114*0b57cec5SDimitry Andric if (!packet_array) 1115*0b57cec5SDimitry Andric return SendErrorResponse(2); 1116*0b57cec5SDimitry Andric 1117*0b57cec5SDimitry Andric JSONArray::SP response_array_sp = std::make_shared<JSONArray>(); 1118*0b57cec5SDimitry Andric for (size_t i = 0; i < packet_array->GetSize(); ++i) { 1119*0b57cec5SDimitry Andric StructuredData::Dictionary *query = 1120*0b57cec5SDimitry Andric packet_array->GetItemAtIndex(i)->GetAsDictionary(); 1121*0b57cec5SDimitry Andric if (!query) 1122*0b57cec5SDimitry Andric continue; 1123*0b57cec5SDimitry Andric llvm::StringRef file, triple; 1124*0b57cec5SDimitry Andric if (!query->GetValueForKeyAsString("file", file) || 1125*0b57cec5SDimitry Andric !query->GetValueForKeyAsString("triple", triple)) 1126*0b57cec5SDimitry Andric continue; 1127*0b57cec5SDimitry Andric 1128*0b57cec5SDimitry Andric ModuleSpec matched_module_spec = GetModuleInfo(file, triple); 1129*0b57cec5SDimitry Andric if (!matched_module_spec.GetFileSpec()) 1130*0b57cec5SDimitry Andric continue; 1131*0b57cec5SDimitry Andric 1132*0b57cec5SDimitry Andric const auto file_offset = matched_module_spec.GetObjectOffset(); 1133*0b57cec5SDimitry Andric const auto file_size = matched_module_spec.GetObjectSize(); 1134*0b57cec5SDimitry Andric const auto uuid_str = matched_module_spec.GetUUID().GetAsString(""); 1135*0b57cec5SDimitry Andric 1136*0b57cec5SDimitry Andric if (uuid_str.empty()) 1137*0b57cec5SDimitry Andric continue; 1138*0b57cec5SDimitry Andric 1139*0b57cec5SDimitry Andric JSONObject::SP response = std::make_shared<JSONObject>(); 1140*0b57cec5SDimitry Andric response_array_sp->AppendObject(response); 1141*0b57cec5SDimitry Andric response->SetObject("uuid", std::make_shared<JSONString>(uuid_str)); 1142*0b57cec5SDimitry Andric response->SetObject( 1143*0b57cec5SDimitry Andric "triple", 1144*0b57cec5SDimitry Andric std::make_shared<JSONString>( 1145*0b57cec5SDimitry Andric matched_module_spec.GetArchitecture().GetTriple().getTriple())); 1146*0b57cec5SDimitry Andric response->SetObject("file_path", 1147*0b57cec5SDimitry Andric std::make_shared<JSONString>( 1148*0b57cec5SDimitry Andric matched_module_spec.GetFileSpec().GetPath())); 1149*0b57cec5SDimitry Andric response->SetObject("file_offset", 1150*0b57cec5SDimitry Andric std::make_shared<JSONNumber>(file_offset)); 1151*0b57cec5SDimitry Andric response->SetObject("file_size", std::make_shared<JSONNumber>(file_size)); 1152*0b57cec5SDimitry Andric } 1153*0b57cec5SDimitry Andric 1154*0b57cec5SDimitry Andric StreamString response; 1155*0b57cec5SDimitry Andric response_array_sp->Write(response); 1156*0b57cec5SDimitry Andric StreamGDBRemote escaped_response; 1157*0b57cec5SDimitry Andric escaped_response.PutEscapedBytes(response.GetString().data(), 1158*0b57cec5SDimitry Andric response.GetSize()); 1159*0b57cec5SDimitry Andric return SendPacketNoLock(escaped_response.GetString()); 1160*0b57cec5SDimitry Andric } 1161*0b57cec5SDimitry Andric 1162*0b57cec5SDimitry Andric void GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse( 1163*0b57cec5SDimitry Andric const ProcessInstanceInfo &proc_info, StreamString &response) { 1164*0b57cec5SDimitry Andric response.Printf( 1165*0b57cec5SDimitry Andric "pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;", 1166*0b57cec5SDimitry Andric proc_info.GetProcessID(), proc_info.GetParentProcessID(), 1167*0b57cec5SDimitry Andric proc_info.GetUserID(), proc_info.GetGroupID(), 1168*0b57cec5SDimitry Andric proc_info.GetEffectiveUserID(), proc_info.GetEffectiveGroupID()); 1169*0b57cec5SDimitry Andric response.PutCString("name:"); 1170*0b57cec5SDimitry Andric response.PutStringAsRawHex8(proc_info.GetExecutableFile().GetCString()); 1171*0b57cec5SDimitry Andric response.PutChar(';'); 1172*0b57cec5SDimitry Andric const ArchSpec &proc_arch = proc_info.GetArchitecture(); 1173*0b57cec5SDimitry Andric if (proc_arch.IsValid()) { 1174*0b57cec5SDimitry Andric const llvm::Triple &proc_triple = proc_arch.GetTriple(); 1175*0b57cec5SDimitry Andric response.PutCString("triple:"); 1176*0b57cec5SDimitry Andric response.PutStringAsRawHex8(proc_triple.getTriple()); 1177*0b57cec5SDimitry Andric response.PutChar(';'); 1178*0b57cec5SDimitry Andric } 1179*0b57cec5SDimitry Andric } 1180*0b57cec5SDimitry Andric 1181*0b57cec5SDimitry Andric void GDBRemoteCommunicationServerCommon:: 1182*0b57cec5SDimitry Andric CreateProcessInfoResponse_DebugServerStyle( 1183*0b57cec5SDimitry Andric const ProcessInstanceInfo &proc_info, StreamString &response) { 1184*0b57cec5SDimitry Andric response.Printf("pid:%" PRIx64 ";parent-pid:%" PRIx64 1185*0b57cec5SDimitry Andric ";real-uid:%x;real-gid:%x;effective-uid:%x;effective-gid:%x;", 1186*0b57cec5SDimitry Andric proc_info.GetProcessID(), proc_info.GetParentProcessID(), 1187*0b57cec5SDimitry Andric proc_info.GetUserID(), proc_info.GetGroupID(), 1188*0b57cec5SDimitry Andric proc_info.GetEffectiveUserID(), 1189*0b57cec5SDimitry Andric proc_info.GetEffectiveGroupID()); 1190*0b57cec5SDimitry Andric 1191*0b57cec5SDimitry Andric const ArchSpec &proc_arch = proc_info.GetArchitecture(); 1192*0b57cec5SDimitry Andric if (proc_arch.IsValid()) { 1193*0b57cec5SDimitry Andric const llvm::Triple &proc_triple = proc_arch.GetTriple(); 1194*0b57cec5SDimitry Andric #if defined(__APPLE__) 1195*0b57cec5SDimitry Andric // We'll send cputype/cpusubtype. 1196*0b57cec5SDimitry Andric const uint32_t cpu_type = proc_arch.GetMachOCPUType(); 1197*0b57cec5SDimitry Andric if (cpu_type != 0) 1198*0b57cec5SDimitry Andric response.Printf("cputype:%" PRIx32 ";", cpu_type); 1199*0b57cec5SDimitry Andric 1200*0b57cec5SDimitry Andric const uint32_t cpu_subtype = proc_arch.GetMachOCPUSubType(); 1201*0b57cec5SDimitry Andric if (cpu_subtype != 0) 1202*0b57cec5SDimitry Andric response.Printf("cpusubtype:%" PRIx32 ";", cpu_subtype); 1203*0b57cec5SDimitry Andric 1204*0b57cec5SDimitry Andric const std::string vendor = proc_triple.getVendorName(); 1205*0b57cec5SDimitry Andric if (!vendor.empty()) 1206*0b57cec5SDimitry Andric response.Printf("vendor:%s;", vendor.c_str()); 1207*0b57cec5SDimitry Andric #else 1208*0b57cec5SDimitry Andric // We'll send the triple. 1209*0b57cec5SDimitry Andric response.PutCString("triple:"); 1210*0b57cec5SDimitry Andric response.PutStringAsRawHex8(proc_triple.getTriple()); 1211*0b57cec5SDimitry Andric response.PutChar(';'); 1212*0b57cec5SDimitry Andric #endif 1213*0b57cec5SDimitry Andric std::string ostype = proc_triple.getOSName(); 1214*0b57cec5SDimitry Andric // Adjust so ostype reports ios for Apple/ARM and Apple/ARM64. 1215*0b57cec5SDimitry Andric if (proc_triple.getVendor() == llvm::Triple::Apple) { 1216*0b57cec5SDimitry Andric switch (proc_triple.getArch()) { 1217*0b57cec5SDimitry Andric case llvm::Triple::arm: 1218*0b57cec5SDimitry Andric case llvm::Triple::thumb: 1219*0b57cec5SDimitry Andric case llvm::Triple::aarch64: 1220*0b57cec5SDimitry Andric ostype = "ios"; 1221*0b57cec5SDimitry Andric break; 1222*0b57cec5SDimitry Andric default: 1223*0b57cec5SDimitry Andric // No change. 1224*0b57cec5SDimitry Andric break; 1225*0b57cec5SDimitry Andric } 1226*0b57cec5SDimitry Andric } 1227*0b57cec5SDimitry Andric response.Printf("ostype:%s;", ostype.c_str()); 1228*0b57cec5SDimitry Andric 1229*0b57cec5SDimitry Andric switch (proc_arch.GetByteOrder()) { 1230*0b57cec5SDimitry Andric case lldb::eByteOrderLittle: 1231*0b57cec5SDimitry Andric response.PutCString("endian:little;"); 1232*0b57cec5SDimitry Andric break; 1233*0b57cec5SDimitry Andric case lldb::eByteOrderBig: 1234*0b57cec5SDimitry Andric response.PutCString("endian:big;"); 1235*0b57cec5SDimitry Andric break; 1236*0b57cec5SDimitry Andric case lldb::eByteOrderPDP: 1237*0b57cec5SDimitry Andric response.PutCString("endian:pdp;"); 1238*0b57cec5SDimitry Andric break; 1239*0b57cec5SDimitry Andric default: 1240*0b57cec5SDimitry Andric // Nothing. 1241*0b57cec5SDimitry Andric break; 1242*0b57cec5SDimitry Andric } 1243*0b57cec5SDimitry Andric // In case of MIPS64, pointer size is depend on ELF ABI For N32 the pointer 1244*0b57cec5SDimitry Andric // size is 4 and for N64 it is 8 1245*0b57cec5SDimitry Andric std::string abi = proc_arch.GetTargetABI(); 1246*0b57cec5SDimitry Andric if (!abi.empty()) 1247*0b57cec5SDimitry Andric response.Printf("elf_abi:%s;", abi.c_str()); 1248*0b57cec5SDimitry Andric response.Printf("ptrsize:%d;", proc_arch.GetAddressByteSize()); 1249*0b57cec5SDimitry Andric } 1250*0b57cec5SDimitry Andric } 1251*0b57cec5SDimitry Andric 1252*0b57cec5SDimitry Andric FileSpec GDBRemoteCommunicationServerCommon::FindModuleFile( 1253*0b57cec5SDimitry Andric const std::string &module_path, const ArchSpec &arch) { 1254*0b57cec5SDimitry Andric #ifdef __ANDROID__ 1255*0b57cec5SDimitry Andric return HostInfoAndroid::ResolveLibraryPath(module_path, arch); 1256*0b57cec5SDimitry Andric #else 1257*0b57cec5SDimitry Andric FileSpec file_spec(module_path); 1258*0b57cec5SDimitry Andric FileSystem::Instance().Resolve(file_spec); 1259*0b57cec5SDimitry Andric return file_spec; 1260*0b57cec5SDimitry Andric #endif 1261*0b57cec5SDimitry Andric } 1262*0b57cec5SDimitry Andric 1263*0b57cec5SDimitry Andric ModuleSpec 1264*0b57cec5SDimitry Andric GDBRemoteCommunicationServerCommon::GetModuleInfo(llvm::StringRef module_path, 1265*0b57cec5SDimitry Andric llvm::StringRef triple) { 1266*0b57cec5SDimitry Andric ArchSpec arch(triple); 1267*0b57cec5SDimitry Andric 1268*0b57cec5SDimitry Andric FileSpec req_module_path_spec(module_path); 1269*0b57cec5SDimitry Andric FileSystem::Instance().Resolve(req_module_path_spec); 1270*0b57cec5SDimitry Andric 1271*0b57cec5SDimitry Andric const FileSpec module_path_spec = 1272*0b57cec5SDimitry Andric FindModuleFile(req_module_path_spec.GetPath(), arch); 1273*0b57cec5SDimitry Andric const ModuleSpec module_spec(module_path_spec, arch); 1274*0b57cec5SDimitry Andric 1275*0b57cec5SDimitry Andric ModuleSpecList module_specs; 1276*0b57cec5SDimitry Andric if (!ObjectFile::GetModuleSpecifications(module_path_spec, 0, 0, 1277*0b57cec5SDimitry Andric module_specs)) 1278*0b57cec5SDimitry Andric return ModuleSpec(); 1279*0b57cec5SDimitry Andric 1280*0b57cec5SDimitry Andric ModuleSpec matched_module_spec; 1281*0b57cec5SDimitry Andric if (!module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) 1282*0b57cec5SDimitry Andric return ModuleSpec(); 1283*0b57cec5SDimitry Andric 1284*0b57cec5SDimitry Andric return matched_module_spec; 1285*0b57cec5SDimitry Andric } 1286