15ffd83dbSDimitry Andric //===-- PlatformRemoteGDBServer.cpp ---------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "PlatformRemoteGDBServer.h" 100b57cec5SDimitry Andric #include "lldb/Host/Config.h" 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointLocation.h" 130b57cec5SDimitry Andric #include "lldb/Core/Debugger.h" 140b57cec5SDimitry Andric #include "lldb/Core/Module.h" 150b57cec5SDimitry Andric #include "lldb/Core/ModuleList.h" 160b57cec5SDimitry Andric #include "lldb/Core/ModuleSpec.h" 170b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h" 180b57cec5SDimitry Andric #include "lldb/Core/StreamFile.h" 190b57cec5SDimitry Andric #include "lldb/Host/ConnectionFileDescriptor.h" 200b57cec5SDimitry Andric #include "lldb/Host/Host.h" 210b57cec5SDimitry Andric #include "lldb/Host/HostInfo.h" 220b57cec5SDimitry Andric #include "lldb/Host/PosixApi.h" 230b57cec5SDimitry Andric #include "lldb/Target/Process.h" 240b57cec5SDimitry Andric #include "lldb/Target/Target.h" 250b57cec5SDimitry Andric #include "lldb/Utility/FileSpec.h" 260b57cec5SDimitry Andric #include "lldb/Utility/Log.h" 270b57cec5SDimitry Andric #include "lldb/Utility/ProcessInfo.h" 280b57cec5SDimitry Andric #include "lldb/Utility/Status.h" 290b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h" 300b57cec5SDimitry Andric #include "lldb/Utility/UriParser.h" 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric #include "Plugins/Process/Utility/GDBRemoteSignals.h" 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric using namespace lldb; 350b57cec5SDimitry Andric using namespace lldb_private; 360b57cec5SDimitry Andric using namespace lldb_private::platform_gdb_server; 370b57cec5SDimitry Andric 385ffd83dbSDimitry Andric LLDB_PLUGIN_DEFINE_ADV(PlatformRemoteGDBServer, PlatformGDB) 395ffd83dbSDimitry Andric 400b57cec5SDimitry Andric static bool g_initialized = false; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric void PlatformRemoteGDBServer::Initialize() { 430b57cec5SDimitry Andric Platform::Initialize(); 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric if (!g_initialized) { 460b57cec5SDimitry Andric g_initialized = true; 470b57cec5SDimitry Andric PluginManager::RegisterPlugin( 480b57cec5SDimitry Andric PlatformRemoteGDBServer::GetPluginNameStatic(), 490b57cec5SDimitry Andric PlatformRemoteGDBServer::GetDescriptionStatic(), 500b57cec5SDimitry Andric PlatformRemoteGDBServer::CreateInstance); 510b57cec5SDimitry Andric } 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric void PlatformRemoteGDBServer::Terminate() { 550b57cec5SDimitry Andric if (g_initialized) { 560b57cec5SDimitry Andric g_initialized = false; 570b57cec5SDimitry Andric PluginManager::UnregisterPlugin(PlatformRemoteGDBServer::CreateInstance); 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric Platform::Terminate(); 610b57cec5SDimitry Andric } 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric PlatformSP PlatformRemoteGDBServer::CreateInstance(bool force, 640b57cec5SDimitry Andric const ArchSpec *arch) { 650b57cec5SDimitry Andric bool create = force; 660b57cec5SDimitry Andric if (!create) { 670b57cec5SDimitry Andric create = !arch->TripleVendorWasSpecified() && !arch->TripleOSWasSpecified(); 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric if (create) 700b57cec5SDimitry Andric return PlatformSP(new PlatformRemoteGDBServer()); 710b57cec5SDimitry Andric return PlatformSP(); 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric ConstString PlatformRemoteGDBServer::GetPluginNameStatic() { 750b57cec5SDimitry Andric static ConstString g_name("remote-gdb-server"); 760b57cec5SDimitry Andric return g_name; 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric const char *PlatformRemoteGDBServer::GetDescriptionStatic() { 800b57cec5SDimitry Andric return "A platform that uses the GDB remote protocol as the communication " 810b57cec5SDimitry Andric "transport."; 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric const char *PlatformRemoteGDBServer::GetDescription() { 850b57cec5SDimitry Andric if (m_platform_description.empty()) { 860b57cec5SDimitry Andric if (IsConnected()) { 870b57cec5SDimitry Andric // Send the get description packet 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric if (!m_platform_description.empty()) 920b57cec5SDimitry Andric return m_platform_description.c_str(); 930b57cec5SDimitry Andric return GetDescriptionStatic(); 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric Status PlatformRemoteGDBServer::ResolveExecutable( 970b57cec5SDimitry Andric const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp, 980b57cec5SDimitry Andric const FileSpecList *module_search_paths_ptr) { 990b57cec5SDimitry Andric // copied from PlatformRemoteiOS 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric Status error; 1020b57cec5SDimitry Andric // Nothing special to do here, just use the actual file and architecture 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric ModuleSpec resolved_module_spec(module_spec); 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric // Resolve any executable within an apk on Android? 1070b57cec5SDimitry Andric // Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec()); 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()) || 1100b57cec5SDimitry Andric module_spec.GetUUID().IsValid()) { 1110b57cec5SDimitry Andric if (resolved_module_spec.GetArchitecture().IsValid() || 1120b57cec5SDimitry Andric resolved_module_spec.GetUUID().IsValid()) { 1130b57cec5SDimitry Andric error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, 1140b57cec5SDimitry Andric module_search_paths_ptr, nullptr, 1150b57cec5SDimitry Andric nullptr); 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric if (exe_module_sp && exe_module_sp->GetObjectFile()) 1180b57cec5SDimitry Andric return error; 1190b57cec5SDimitry Andric exe_module_sp.reset(); 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric // No valid architecture was specified or the exact arch wasn't found so 1220b57cec5SDimitry Andric // ask the platform for the architectures that we should be using (in the 1230b57cec5SDimitry Andric // correct order) and see if we can find a match that way 1240b57cec5SDimitry Andric StreamString arch_names; 1250b57cec5SDimitry Andric for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( 1260b57cec5SDimitry Andric idx, resolved_module_spec.GetArchitecture()); 1270b57cec5SDimitry Andric ++idx) { 1280b57cec5SDimitry Andric error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, 1290b57cec5SDimitry Andric module_search_paths_ptr, nullptr, 1300b57cec5SDimitry Andric nullptr); 1310b57cec5SDimitry Andric // Did we find an executable using one of the 1320b57cec5SDimitry Andric if (error.Success()) { 1330b57cec5SDimitry Andric if (exe_module_sp && exe_module_sp->GetObjectFile()) 1340b57cec5SDimitry Andric break; 1350b57cec5SDimitry Andric else 1360b57cec5SDimitry Andric error.SetErrorToGenericError(); 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric if (idx > 0) 1400b57cec5SDimitry Andric arch_names.PutCString(", "); 1410b57cec5SDimitry Andric arch_names.PutCString( 1420b57cec5SDimitry Andric resolved_module_spec.GetArchitecture().GetArchitectureName()); 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric if (error.Fail() || !exe_module_sp) { 1460b57cec5SDimitry Andric if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) { 1470b57cec5SDimitry Andric error.SetErrorStringWithFormat( 1480b57cec5SDimitry Andric "'%s' doesn't contain any '%s' platform architectures: %s", 1490b57cec5SDimitry Andric resolved_module_spec.GetFileSpec().GetPath().c_str(), 1500b57cec5SDimitry Andric GetPluginName().GetCString(), arch_names.GetData()); 1510b57cec5SDimitry Andric } else { 1520b57cec5SDimitry Andric error.SetErrorStringWithFormat( 1530b57cec5SDimitry Andric "'%s' is not readable", 1540b57cec5SDimitry Andric resolved_module_spec.GetFileSpec().GetPath().c_str()); 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric } else { 1580b57cec5SDimitry Andric error.SetErrorStringWithFormat( 1590b57cec5SDimitry Andric "'%s' does not exist", 1600b57cec5SDimitry Andric resolved_module_spec.GetFileSpec().GetPath().c_str()); 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric return error; 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric bool PlatformRemoteGDBServer::GetModuleSpec(const FileSpec &module_file_spec, 1670b57cec5SDimitry Andric const ArchSpec &arch, 1680b57cec5SDimitry Andric ModuleSpec &module_spec) { 1690b57cec5SDimitry Andric Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric const auto module_path = module_file_spec.GetPath(false); 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric if (!m_gdb_client.GetModuleInfo(module_file_spec, arch, module_spec)) { 1749dba64beSDimitry Andric LLDB_LOGF( 1759dba64beSDimitry Andric log, 1760b57cec5SDimitry Andric "PlatformRemoteGDBServer::%s - failed to get module info for %s:%s", 1770b57cec5SDimitry Andric __FUNCTION__, module_path.c_str(), 1780b57cec5SDimitry Andric arch.GetTriple().getTriple().c_str()); 1790b57cec5SDimitry Andric return false; 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric if (log) { 1830b57cec5SDimitry Andric StreamString stream; 1840b57cec5SDimitry Andric module_spec.Dump(stream); 1859dba64beSDimitry Andric LLDB_LOGF(log, 1860b57cec5SDimitry Andric "PlatformRemoteGDBServer::%s - got module info for (%s:%s) : %s", 1879dba64beSDimitry Andric __FUNCTION__, module_path.c_str(), 1889dba64beSDimitry Andric arch.GetTriple().getTriple().c_str(), stream.GetData()); 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric return true; 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric Status PlatformRemoteGDBServer::GetFileWithUUID(const FileSpec &platform_file, 1950b57cec5SDimitry Andric const UUID *uuid_ptr, 1960b57cec5SDimitry Andric FileSpec &local_file) { 1970b57cec5SDimitry Andric // Default to the local case 1980b57cec5SDimitry Andric local_file = platform_file; 1990b57cec5SDimitry Andric return Status(); 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric /// Default Constructor 2030b57cec5SDimitry Andric PlatformRemoteGDBServer::PlatformRemoteGDBServer() 2040b57cec5SDimitry Andric : Platform(false), // This is a remote platform 2050b57cec5SDimitry Andric m_gdb_client() {} 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric /// Destructor. 2080b57cec5SDimitry Andric /// 2090b57cec5SDimitry Andric /// The destructor is virtual since this class is designed to be 2100b57cec5SDimitry Andric /// inherited from by the plug-in instance. 2110b57cec5SDimitry Andric PlatformRemoteGDBServer::~PlatformRemoteGDBServer() {} 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric bool PlatformRemoteGDBServer::GetSupportedArchitectureAtIndex(uint32_t idx, 2140b57cec5SDimitry Andric ArchSpec &arch) { 2150b57cec5SDimitry Andric ArchSpec remote_arch = m_gdb_client.GetSystemArchitecture(); 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric if (idx == 0) { 2180b57cec5SDimitry Andric arch = remote_arch; 2190b57cec5SDimitry Andric return arch.IsValid(); 2200b57cec5SDimitry Andric } else if (idx == 1 && remote_arch.IsValid() && 2210b57cec5SDimitry Andric remote_arch.GetTriple().isArch64Bit()) { 2220b57cec5SDimitry Andric arch.SetTriple(remote_arch.GetTriple().get32BitArchVariant()); 2230b57cec5SDimitry Andric return arch.IsValid(); 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric return false; 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric size_t PlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode( 2290b57cec5SDimitry Andric Target &target, BreakpointSite *bp_site) { 2300b57cec5SDimitry Andric // This isn't needed if the z/Z packets are supported in the GDB remote 2310b57cec5SDimitry Andric // server. But we might need a packet to detect this. 2320b57cec5SDimitry Andric return 0; 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric bool PlatformRemoteGDBServer::GetRemoteOSVersion() { 2360b57cec5SDimitry Andric m_os_version = m_gdb_client.GetOSVersion(); 2370b57cec5SDimitry Andric return !m_os_version.empty(); 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric bool PlatformRemoteGDBServer::GetRemoteOSBuildString(std::string &s) { 2410b57cec5SDimitry Andric return m_gdb_client.GetOSBuildString(s); 2420b57cec5SDimitry Andric } 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric bool PlatformRemoteGDBServer::GetRemoteOSKernelDescription(std::string &s) { 2450b57cec5SDimitry Andric return m_gdb_client.GetOSKernelDescription(s); 2460b57cec5SDimitry Andric } 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric // Remote Platform subclasses need to override this function 2490b57cec5SDimitry Andric ArchSpec PlatformRemoteGDBServer::GetRemoteSystemArchitecture() { 2500b57cec5SDimitry Andric return m_gdb_client.GetSystemArchitecture(); 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric FileSpec PlatformRemoteGDBServer::GetRemoteWorkingDirectory() { 2540b57cec5SDimitry Andric if (IsConnected()) { 2550b57cec5SDimitry Andric Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 2560b57cec5SDimitry Andric FileSpec working_dir; 2570b57cec5SDimitry Andric if (m_gdb_client.GetWorkingDir(working_dir) && log) 2589dba64beSDimitry Andric LLDB_LOGF(log, 2590b57cec5SDimitry Andric "PlatformRemoteGDBServer::GetRemoteWorkingDirectory() -> '%s'", 2600b57cec5SDimitry Andric working_dir.GetCString()); 2610b57cec5SDimitry Andric return working_dir; 2620b57cec5SDimitry Andric } else { 2630b57cec5SDimitry Andric return Platform::GetRemoteWorkingDirectory(); 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric bool PlatformRemoteGDBServer::SetRemoteWorkingDirectory( 2680b57cec5SDimitry Andric const FileSpec &working_dir) { 2690b57cec5SDimitry Andric if (IsConnected()) { 2700b57cec5SDimitry Andric // Clear the working directory it case it doesn't get set correctly. This 2710b57cec5SDimitry Andric // will for use to re-read it 2720b57cec5SDimitry Andric Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 2739dba64beSDimitry Andric LLDB_LOGF(log, "PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')", 2740b57cec5SDimitry Andric working_dir.GetCString()); 2750b57cec5SDimitry Andric return m_gdb_client.SetWorkingDir(working_dir) == 0; 2760b57cec5SDimitry Andric } else 2770b57cec5SDimitry Andric return Platform::SetRemoteWorkingDirectory(working_dir); 2780b57cec5SDimitry Andric } 2790b57cec5SDimitry Andric 2800b57cec5SDimitry Andric bool PlatformRemoteGDBServer::IsConnected() const { 2810b57cec5SDimitry Andric return m_gdb_client.IsConnected(); 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric Status PlatformRemoteGDBServer::ConnectRemote(Args &args) { 2850b57cec5SDimitry Andric Status error; 2860b57cec5SDimitry Andric if (IsConnected()) { 2870b57cec5SDimitry Andric error.SetErrorStringWithFormat("the platform is already connected to '%s', " 2880b57cec5SDimitry Andric "execute 'platform disconnect' to close the " 2890b57cec5SDimitry Andric "current connection", 2900b57cec5SDimitry Andric GetHostname()); 2915ffd83dbSDimitry Andric return error; 2925ffd83dbSDimitry Andric } 2935ffd83dbSDimitry Andric 2945ffd83dbSDimitry Andric if (args.GetArgumentCount() != 1) { 2955ffd83dbSDimitry Andric error.SetErrorString( 2965ffd83dbSDimitry Andric "\"platform connect\" takes a single argument: <connect-url>"); 2975ffd83dbSDimitry Andric return error; 2985ffd83dbSDimitry Andric } 2995ffd83dbSDimitry Andric 3000b57cec5SDimitry Andric const char *url = args.GetArgumentAtIndex(0); 3010b57cec5SDimitry Andric if (!url) 3020b57cec5SDimitry Andric return Status("URL is null."); 3035ffd83dbSDimitry Andric 3045ffd83dbSDimitry Andric int port; 3050b57cec5SDimitry Andric llvm::StringRef scheme, hostname, pathname; 3060b57cec5SDimitry Andric if (!UriParser::Parse(url, scheme, hostname, port, pathname)) 3070b57cec5SDimitry Andric return Status("Invalid URL: %s", url); 3080b57cec5SDimitry Andric 3095ffd83dbSDimitry Andric // We're going to reuse the hostname when we connect to the debugserver. 3105ffd83dbSDimitry Andric m_platform_scheme = std::string(scheme); 3115ffd83dbSDimitry Andric m_platform_hostname = std::string(hostname); 3125ffd83dbSDimitry Andric 3135ffd83dbSDimitry Andric m_gdb_client.SetConnection(std::make_unique<ConnectionFileDescriptor>()); 3145ffd83dbSDimitry Andric if (repro::Reproducer::Instance().IsReplaying()) { 3155ffd83dbSDimitry Andric error = m_gdb_replay_server.Connect(m_gdb_client); 3165ffd83dbSDimitry Andric if (error.Success()) 3175ffd83dbSDimitry Andric m_gdb_replay_server.StartAsyncThread(); 3185ffd83dbSDimitry Andric } else { 3195ffd83dbSDimitry Andric if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) { 3205ffd83dbSDimitry Andric repro::GDBRemoteProvider &provider = 3215ffd83dbSDimitry Andric g->GetOrCreate<repro::GDBRemoteProvider>(); 3225ffd83dbSDimitry Andric m_gdb_client.SetPacketRecorder(provider.GetNewPacketRecorder()); 3235ffd83dbSDimitry Andric } 3245ffd83dbSDimitry Andric m_gdb_client.Connect(url, &error); 3255ffd83dbSDimitry Andric } 3265ffd83dbSDimitry Andric 3275ffd83dbSDimitry Andric if (error.Fail()) 3285ffd83dbSDimitry Andric return error; 3295ffd83dbSDimitry Andric 3300b57cec5SDimitry Andric if (m_gdb_client.HandshakeWithServer(&error)) { 3310b57cec5SDimitry Andric m_gdb_client.GetHostInfo(); 3320b57cec5SDimitry Andric // If a working directory was set prior to connecting, send it down 3335ffd83dbSDimitry Andric // now. 3340b57cec5SDimitry Andric if (m_working_dir) 3350b57cec5SDimitry Andric m_gdb_client.SetWorkingDir(m_working_dir); 3360b57cec5SDimitry Andric } else { 3370b57cec5SDimitry Andric m_gdb_client.Disconnect(); 3380b57cec5SDimitry Andric if (error.Success()) 3390b57cec5SDimitry Andric error.SetErrorString("handshake failed"); 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric return error; 3420b57cec5SDimitry Andric } 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric Status PlatformRemoteGDBServer::DisconnectRemote() { 3450b57cec5SDimitry Andric Status error; 3460b57cec5SDimitry Andric m_gdb_client.Disconnect(&error); 3470b57cec5SDimitry Andric m_remote_signals_sp.reset(); 3480b57cec5SDimitry Andric return error; 3490b57cec5SDimitry Andric } 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric const char *PlatformRemoteGDBServer::GetHostname() { 3520b57cec5SDimitry Andric m_gdb_client.GetHostname(m_name); 3530b57cec5SDimitry Andric if (m_name.empty()) 3540b57cec5SDimitry Andric return nullptr; 3550b57cec5SDimitry Andric return m_name.c_str(); 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric llvm::Optional<std::string> 3590b57cec5SDimitry Andric PlatformRemoteGDBServer::DoGetUserName(UserIDResolver::id_t uid) { 3600b57cec5SDimitry Andric std::string name; 3610b57cec5SDimitry Andric if (m_gdb_client.GetUserName(uid, name)) 3620b57cec5SDimitry Andric return std::move(name); 3630b57cec5SDimitry Andric return llvm::None; 3640b57cec5SDimitry Andric } 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric llvm::Optional<std::string> 3670b57cec5SDimitry Andric PlatformRemoteGDBServer::DoGetGroupName(UserIDResolver::id_t gid) { 3680b57cec5SDimitry Andric std::string name; 3690b57cec5SDimitry Andric if (m_gdb_client.GetGroupName(gid, name)) 3700b57cec5SDimitry Andric return std::move(name); 3710b57cec5SDimitry Andric return llvm::None; 3720b57cec5SDimitry Andric } 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric uint32_t PlatformRemoteGDBServer::FindProcesses( 3750b57cec5SDimitry Andric const ProcessInstanceInfoMatch &match_info, 3760b57cec5SDimitry Andric ProcessInstanceInfoList &process_infos) { 3770b57cec5SDimitry Andric return m_gdb_client.FindProcesses(match_info, process_infos); 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric bool PlatformRemoteGDBServer::GetProcessInfo( 3810b57cec5SDimitry Andric lldb::pid_t pid, ProcessInstanceInfo &process_info) { 3820b57cec5SDimitry Andric return m_gdb_client.GetProcessInfo(pid, process_info); 3830b57cec5SDimitry Andric } 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) { 3860b57cec5SDimitry Andric Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); 3870b57cec5SDimitry Andric Status error; 3880b57cec5SDimitry Andric 3899dba64beSDimitry Andric LLDB_LOGF(log, "PlatformRemoteGDBServer::%s() called", __FUNCTION__); 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric auto num_file_actions = launch_info.GetNumFileActions(); 3920b57cec5SDimitry Andric for (decltype(num_file_actions) i = 0; i < num_file_actions; ++i) { 3930b57cec5SDimitry Andric const auto file_action = launch_info.GetFileActionAtIndex(i); 3940b57cec5SDimitry Andric if (file_action->GetAction() != FileAction::eFileActionOpen) 3950b57cec5SDimitry Andric continue; 3960b57cec5SDimitry Andric switch (file_action->GetFD()) { 3970b57cec5SDimitry Andric case STDIN_FILENO: 3980b57cec5SDimitry Andric m_gdb_client.SetSTDIN(file_action->GetFileSpec()); 3990b57cec5SDimitry Andric break; 4000b57cec5SDimitry Andric case STDOUT_FILENO: 4010b57cec5SDimitry Andric m_gdb_client.SetSTDOUT(file_action->GetFileSpec()); 4020b57cec5SDimitry Andric break; 4030b57cec5SDimitry Andric case STDERR_FILENO: 4040b57cec5SDimitry Andric m_gdb_client.SetSTDERR(file_action->GetFileSpec()); 4050b57cec5SDimitry Andric break; 4060b57cec5SDimitry Andric } 4070b57cec5SDimitry Andric } 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric m_gdb_client.SetDisableASLR( 4100b57cec5SDimitry Andric launch_info.GetFlags().Test(eLaunchFlagDisableASLR)); 4110b57cec5SDimitry Andric m_gdb_client.SetDetachOnError( 4120b57cec5SDimitry Andric launch_info.GetFlags().Test(eLaunchFlagDetachOnError)); 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric FileSpec working_dir = launch_info.GetWorkingDirectory(); 4150b57cec5SDimitry Andric if (working_dir) { 4160b57cec5SDimitry Andric m_gdb_client.SetWorkingDir(working_dir); 4170b57cec5SDimitry Andric } 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric // Send the environment and the program + arguments after we connect 4200b57cec5SDimitry Andric m_gdb_client.SendEnvironment(launch_info.GetEnvironment()); 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric ArchSpec arch_spec = launch_info.GetArchitecture(); 4230b57cec5SDimitry Andric const char *arch_triple = arch_spec.GetTriple().str().c_str(); 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric m_gdb_client.SendLaunchArchPacket(arch_triple); 4269dba64beSDimitry Andric LLDB_LOGF( 4279dba64beSDimitry Andric log, 4280b57cec5SDimitry Andric "PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'", 4290b57cec5SDimitry Andric __FUNCTION__, arch_triple ? arch_triple : "<NULL>"); 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric int arg_packet_err; 4320b57cec5SDimitry Andric { 4330b57cec5SDimitry Andric // Scope for the scoped timeout object 4340b57cec5SDimitry Andric process_gdb_remote::GDBRemoteCommunication::ScopedTimeout timeout( 4350b57cec5SDimitry Andric m_gdb_client, std::chrono::seconds(5)); 4360b57cec5SDimitry Andric arg_packet_err = m_gdb_client.SendArgumentsPacket(launch_info); 4370b57cec5SDimitry Andric } 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric if (arg_packet_err == 0) { 4400b57cec5SDimitry Andric std::string error_str; 4410b57cec5SDimitry Andric if (m_gdb_client.GetLaunchSuccess(error_str)) { 4420b57cec5SDimitry Andric const auto pid = m_gdb_client.GetCurrentProcessID(false); 4430b57cec5SDimitry Andric if (pid != LLDB_INVALID_PROCESS_ID) { 4440b57cec5SDimitry Andric launch_info.SetProcessID(pid); 4459dba64beSDimitry Andric LLDB_LOGF(log, 4469dba64beSDimitry Andric "PlatformRemoteGDBServer::%s() pid %" PRIu64 4470b57cec5SDimitry Andric " launched successfully", 4480b57cec5SDimitry Andric __FUNCTION__, pid); 4490b57cec5SDimitry Andric } else { 4509dba64beSDimitry Andric LLDB_LOGF(log, 4519dba64beSDimitry Andric "PlatformRemoteGDBServer::%s() launch succeeded but we " 4520b57cec5SDimitry Andric "didn't get a valid process id back!", 4530b57cec5SDimitry Andric __FUNCTION__); 4540b57cec5SDimitry Andric error.SetErrorString("failed to get PID"); 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric } else { 4570b57cec5SDimitry Andric error.SetErrorString(error_str.c_str()); 4589dba64beSDimitry Andric LLDB_LOGF(log, "PlatformRemoteGDBServer::%s() launch failed: %s", 4590b57cec5SDimitry Andric __FUNCTION__, error.AsCString()); 4600b57cec5SDimitry Andric } 4610b57cec5SDimitry Andric } else { 4620b57cec5SDimitry Andric error.SetErrorStringWithFormat("'A' packet returned an error: %i", 4630b57cec5SDimitry Andric arg_packet_err); 4640b57cec5SDimitry Andric } 4650b57cec5SDimitry Andric return error; 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric Status PlatformRemoteGDBServer::KillProcess(const lldb::pid_t pid) { 4690b57cec5SDimitry Andric if (!KillSpawnedProcess(pid)) 4700b57cec5SDimitry Andric return Status("failed to kill remote spawned process"); 4710b57cec5SDimitry Andric return Status(); 4720b57cec5SDimitry Andric } 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric lldb::ProcessSP PlatformRemoteGDBServer::DebugProcess( 4750b57cec5SDimitry Andric ProcessLaunchInfo &launch_info, Debugger &debugger, 4760b57cec5SDimitry Andric Target *target, // Can be NULL, if NULL create a new target, else use 4770b57cec5SDimitry Andric // existing one 4780b57cec5SDimitry Andric Status &error) { 4790b57cec5SDimitry Andric lldb::ProcessSP process_sp; 4800b57cec5SDimitry Andric if (IsRemote()) { 4810b57cec5SDimitry Andric if (IsConnected()) { 4820b57cec5SDimitry Andric lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; 4830b57cec5SDimitry Andric std::string connect_url; 4840b57cec5SDimitry Andric if (!LaunchGDBServer(debugserver_pid, connect_url)) { 4850b57cec5SDimitry Andric error.SetErrorStringWithFormat("unable to launch a GDB server on '%s'", 4860b57cec5SDimitry Andric GetHostname()); 4870b57cec5SDimitry Andric } else { 4880b57cec5SDimitry Andric if (target == nullptr) { 4890b57cec5SDimitry Andric TargetSP new_target_sp; 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric error = debugger.GetTargetList().CreateTarget( 4920b57cec5SDimitry Andric debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp); 4930b57cec5SDimitry Andric target = new_target_sp.get(); 4940b57cec5SDimitry Andric } else 4950b57cec5SDimitry Andric error.Clear(); 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric if (target && error.Success()) { 4980b57cec5SDimitry Andric debugger.GetTargetList().SetSelectedTarget(target); 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric // The darwin always currently uses the GDB remote debugger plug-in 5010b57cec5SDimitry Andric // so even when debugging locally we are debugging remotely! 5020b57cec5SDimitry Andric process_sp = target->CreateProcess(launch_info.GetListener(), 5030b57cec5SDimitry Andric "gdb-remote", nullptr); 5040b57cec5SDimitry Andric 5050b57cec5SDimitry Andric if (process_sp) { 5065ffd83dbSDimitry Andric error = process_sp->ConnectRemote(connect_url.c_str()); 5070b57cec5SDimitry Andric // Retry the connect remote one time... 5080b57cec5SDimitry Andric if (error.Fail()) 5095ffd83dbSDimitry Andric error = process_sp->ConnectRemote(connect_url.c_str()); 5100b57cec5SDimitry Andric if (error.Success()) 5110b57cec5SDimitry Andric error = process_sp->Launch(launch_info); 5120b57cec5SDimitry Andric else if (debugserver_pid != LLDB_INVALID_PROCESS_ID) { 5130b57cec5SDimitry Andric printf("error: connect remote failed (%s)\n", error.AsCString()); 5140b57cec5SDimitry Andric KillSpawnedProcess(debugserver_pid); 5150b57cec5SDimitry Andric } 5160b57cec5SDimitry Andric } 5170b57cec5SDimitry Andric } 5180b57cec5SDimitry Andric } 5190b57cec5SDimitry Andric } else { 5200b57cec5SDimitry Andric error.SetErrorString("not connected to remote gdb server"); 5210b57cec5SDimitry Andric } 5220b57cec5SDimitry Andric } 5230b57cec5SDimitry Andric return process_sp; 5240b57cec5SDimitry Andric } 5250b57cec5SDimitry Andric 5260b57cec5SDimitry Andric bool PlatformRemoteGDBServer::LaunchGDBServer(lldb::pid_t &pid, 5270b57cec5SDimitry Andric std::string &connect_url) { 5280b57cec5SDimitry Andric ArchSpec remote_arch = GetRemoteSystemArchitecture(); 5290b57cec5SDimitry Andric llvm::Triple &remote_triple = remote_arch.GetTriple(); 5300b57cec5SDimitry Andric 5310b57cec5SDimitry Andric uint16_t port = 0; 5320b57cec5SDimitry Andric std::string socket_name; 5330b57cec5SDimitry Andric bool launch_result = false; 5340b57cec5SDimitry Andric if (remote_triple.getVendor() == llvm::Triple::Apple && 5350b57cec5SDimitry Andric remote_triple.getOS() == llvm::Triple::IOS) { 5360b57cec5SDimitry Andric // When remote debugging to iOS, we use a USB mux that always talks to 5370b57cec5SDimitry Andric // localhost, so we will need the remote debugserver to accept connections 5380b57cec5SDimitry Andric // only from localhost, no matter what our current hostname is 5390b57cec5SDimitry Andric launch_result = 5400b57cec5SDimitry Andric m_gdb_client.LaunchGDBServer("127.0.0.1", pid, port, socket_name); 5410b57cec5SDimitry Andric } else { 5420b57cec5SDimitry Andric // All other hosts should use their actual hostname 5430b57cec5SDimitry Andric launch_result = 5440b57cec5SDimitry Andric m_gdb_client.LaunchGDBServer(nullptr, pid, port, socket_name); 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andric if (!launch_result) 5480b57cec5SDimitry Andric return false; 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric connect_url = 5510b57cec5SDimitry Andric MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, port, 5520b57cec5SDimitry Andric (socket_name.empty()) ? nullptr : socket_name.c_str()); 5530b57cec5SDimitry Andric return true; 5540b57cec5SDimitry Andric } 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric bool PlatformRemoteGDBServer::KillSpawnedProcess(lldb::pid_t pid) { 5570b57cec5SDimitry Andric return m_gdb_client.KillSpawnedProcess(pid); 5580b57cec5SDimitry Andric } 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric lldb::ProcessSP PlatformRemoteGDBServer::Attach( 5610b57cec5SDimitry Andric ProcessAttachInfo &attach_info, Debugger &debugger, 5620b57cec5SDimitry Andric Target *target, // Can be NULL, if NULL create a new target, else use 5630b57cec5SDimitry Andric // existing one 5640b57cec5SDimitry Andric Status &error) { 5650b57cec5SDimitry Andric lldb::ProcessSP process_sp; 5660b57cec5SDimitry Andric if (IsRemote()) { 5670b57cec5SDimitry Andric if (IsConnected()) { 5680b57cec5SDimitry Andric lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; 5690b57cec5SDimitry Andric std::string connect_url; 5700b57cec5SDimitry Andric if (!LaunchGDBServer(debugserver_pid, connect_url)) { 5710b57cec5SDimitry Andric error.SetErrorStringWithFormat("unable to launch a GDB server on '%s'", 5720b57cec5SDimitry Andric GetHostname()); 5730b57cec5SDimitry Andric } else { 5740b57cec5SDimitry Andric if (target == nullptr) { 5750b57cec5SDimitry Andric TargetSP new_target_sp; 5760b57cec5SDimitry Andric 5770b57cec5SDimitry Andric error = debugger.GetTargetList().CreateTarget( 5780b57cec5SDimitry Andric debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp); 5790b57cec5SDimitry Andric target = new_target_sp.get(); 5800b57cec5SDimitry Andric } else 5810b57cec5SDimitry Andric error.Clear(); 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric if (target && error.Success()) { 5840b57cec5SDimitry Andric debugger.GetTargetList().SetSelectedTarget(target); 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric // The darwin always currently uses the GDB remote debugger plug-in 5870b57cec5SDimitry Andric // so even when debugging locally we are debugging remotely! 5880b57cec5SDimitry Andric process_sp = 5890b57cec5SDimitry Andric target->CreateProcess(attach_info.GetListenerForProcess(debugger), 5900b57cec5SDimitry Andric "gdb-remote", nullptr); 5910b57cec5SDimitry Andric if (process_sp) { 5925ffd83dbSDimitry Andric error = process_sp->ConnectRemote(connect_url.c_str()); 5930b57cec5SDimitry Andric if (error.Success()) { 5940b57cec5SDimitry Andric ListenerSP listener_sp = attach_info.GetHijackListener(); 5950b57cec5SDimitry Andric if (listener_sp) 5960b57cec5SDimitry Andric process_sp->HijackProcessEvents(listener_sp); 5970b57cec5SDimitry Andric error = process_sp->Attach(attach_info); 5980b57cec5SDimitry Andric } 5990b57cec5SDimitry Andric 6000b57cec5SDimitry Andric if (error.Fail() && debugserver_pid != LLDB_INVALID_PROCESS_ID) { 6010b57cec5SDimitry Andric KillSpawnedProcess(debugserver_pid); 6020b57cec5SDimitry Andric } 6030b57cec5SDimitry Andric } 6040b57cec5SDimitry Andric } 6050b57cec5SDimitry Andric } 6060b57cec5SDimitry Andric } else { 6070b57cec5SDimitry Andric error.SetErrorString("not connected to remote gdb server"); 6080b57cec5SDimitry Andric } 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric return process_sp; 6110b57cec5SDimitry Andric } 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric Status PlatformRemoteGDBServer::MakeDirectory(const FileSpec &file_spec, 6140b57cec5SDimitry Andric uint32_t mode) { 6150b57cec5SDimitry Andric Status error = m_gdb_client.MakeDirectory(file_spec, mode); 6160b57cec5SDimitry Andric Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 6179dba64beSDimitry Andric LLDB_LOGF(log, 6189dba64beSDimitry Andric "PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) " 6190b57cec5SDimitry Andric "error = %u (%s)", 6209dba64beSDimitry Andric file_spec.GetCString(), mode, error.GetError(), error.AsCString()); 6210b57cec5SDimitry Andric return error; 6220b57cec5SDimitry Andric } 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric Status PlatformRemoteGDBServer::GetFilePermissions(const FileSpec &file_spec, 6250b57cec5SDimitry Andric uint32_t &file_permissions) { 6260b57cec5SDimitry Andric Status error = m_gdb_client.GetFilePermissions(file_spec, file_permissions); 6270b57cec5SDimitry Andric Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 6289dba64beSDimitry Andric LLDB_LOGF(log, 6299dba64beSDimitry Andric "PlatformRemoteGDBServer::GetFilePermissions(path='%s', " 6300b57cec5SDimitry Andric "file_permissions=%o) error = %u (%s)", 6310b57cec5SDimitry Andric file_spec.GetCString(), file_permissions, error.GetError(), 6320b57cec5SDimitry Andric error.AsCString()); 6330b57cec5SDimitry Andric return error; 6340b57cec5SDimitry Andric } 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric Status PlatformRemoteGDBServer::SetFilePermissions(const FileSpec &file_spec, 6370b57cec5SDimitry Andric uint32_t file_permissions) { 6380b57cec5SDimitry Andric Status error = m_gdb_client.SetFilePermissions(file_spec, file_permissions); 6390b57cec5SDimitry Andric Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 6409dba64beSDimitry Andric LLDB_LOGF(log, 6419dba64beSDimitry Andric "PlatformRemoteGDBServer::SetFilePermissions(path='%s', " 6420b57cec5SDimitry Andric "file_permissions=%o) error = %u (%s)", 6430b57cec5SDimitry Andric file_spec.GetCString(), file_permissions, error.GetError(), 6440b57cec5SDimitry Andric error.AsCString()); 6450b57cec5SDimitry Andric return error; 6460b57cec5SDimitry Andric } 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric lldb::user_id_t PlatformRemoteGDBServer::OpenFile(const FileSpec &file_spec, 6499dba64beSDimitry Andric File::OpenOptions flags, 6509dba64beSDimitry Andric uint32_t mode, 6510b57cec5SDimitry Andric Status &error) { 6520b57cec5SDimitry Andric return m_gdb_client.OpenFile(file_spec, flags, mode, error); 6530b57cec5SDimitry Andric } 6540b57cec5SDimitry Andric 6550b57cec5SDimitry Andric bool PlatformRemoteGDBServer::CloseFile(lldb::user_id_t fd, Status &error) { 6560b57cec5SDimitry Andric return m_gdb_client.CloseFile(fd, error); 6570b57cec5SDimitry Andric } 6580b57cec5SDimitry Andric 6590b57cec5SDimitry Andric lldb::user_id_t 6600b57cec5SDimitry Andric PlatformRemoteGDBServer::GetFileSize(const FileSpec &file_spec) { 6610b57cec5SDimitry Andric return m_gdb_client.GetFileSize(file_spec); 6620b57cec5SDimitry Andric } 6630b57cec5SDimitry Andric 6640b57cec5SDimitry Andric uint64_t PlatformRemoteGDBServer::ReadFile(lldb::user_id_t fd, uint64_t offset, 6650b57cec5SDimitry Andric void *dst, uint64_t dst_len, 6660b57cec5SDimitry Andric Status &error) { 6670b57cec5SDimitry Andric return m_gdb_client.ReadFile(fd, offset, dst, dst_len, error); 6680b57cec5SDimitry Andric } 6690b57cec5SDimitry Andric 6700b57cec5SDimitry Andric uint64_t PlatformRemoteGDBServer::WriteFile(lldb::user_id_t fd, uint64_t offset, 6710b57cec5SDimitry Andric const void *src, uint64_t src_len, 6720b57cec5SDimitry Andric Status &error) { 6730b57cec5SDimitry Andric return m_gdb_client.WriteFile(fd, offset, src, src_len, error); 6740b57cec5SDimitry Andric } 6750b57cec5SDimitry Andric 6760b57cec5SDimitry Andric Status PlatformRemoteGDBServer::PutFile(const FileSpec &source, 6770b57cec5SDimitry Andric const FileSpec &destination, 6780b57cec5SDimitry Andric uint32_t uid, uint32_t gid) { 6790b57cec5SDimitry Andric return Platform::PutFile(source, destination, uid, gid); 6800b57cec5SDimitry Andric } 6810b57cec5SDimitry Andric 6820b57cec5SDimitry Andric Status PlatformRemoteGDBServer::CreateSymlink( 6830b57cec5SDimitry Andric const FileSpec &src, // The name of the link is in src 6840b57cec5SDimitry Andric const FileSpec &dst) // The symlink points to dst 6850b57cec5SDimitry Andric { 6860b57cec5SDimitry Andric Status error = m_gdb_client.CreateSymlink(src, dst); 6870b57cec5SDimitry Andric Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 6889dba64beSDimitry Andric LLDB_LOGF(log, 6899dba64beSDimitry Andric "PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') " 6900b57cec5SDimitry Andric "error = %u (%s)", 6910b57cec5SDimitry Andric src.GetCString(), dst.GetCString(), error.GetError(), 6920b57cec5SDimitry Andric error.AsCString()); 6930b57cec5SDimitry Andric return error; 6940b57cec5SDimitry Andric } 6950b57cec5SDimitry Andric 6960b57cec5SDimitry Andric Status PlatformRemoteGDBServer::Unlink(const FileSpec &file_spec) { 6970b57cec5SDimitry Andric Status error = m_gdb_client.Unlink(file_spec); 6980b57cec5SDimitry Andric Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 6999dba64beSDimitry Andric LLDB_LOGF(log, "PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)", 7000b57cec5SDimitry Andric file_spec.GetCString(), error.GetError(), error.AsCString()); 7010b57cec5SDimitry Andric return error; 7020b57cec5SDimitry Andric } 7030b57cec5SDimitry Andric 7040b57cec5SDimitry Andric bool PlatformRemoteGDBServer::GetFileExists(const FileSpec &file_spec) { 7050b57cec5SDimitry Andric return m_gdb_client.GetFileExists(file_spec); 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric Status PlatformRemoteGDBServer::RunShellCommand( 7090b57cec5SDimitry Andric const char *command, // Shouldn't be NULL 7100b57cec5SDimitry Andric const FileSpec & 7110b57cec5SDimitry Andric working_dir, // Pass empty FileSpec to use the current working directory 7120b57cec5SDimitry Andric int *status_ptr, // Pass NULL if you don't want the process exit status 7130b57cec5SDimitry Andric int *signo_ptr, // Pass NULL if you don't want the signal that caused the 7140b57cec5SDimitry Andric // process to exit 7150b57cec5SDimitry Andric std::string 7160b57cec5SDimitry Andric *command_output, // Pass NULL if you don't want the command output 7170b57cec5SDimitry Andric const Timeout<std::micro> &timeout) { 7180b57cec5SDimitry Andric return m_gdb_client.RunShellCommand(command, working_dir, status_ptr, 7190b57cec5SDimitry Andric signo_ptr, command_output, timeout); 7200b57cec5SDimitry Andric } 7210b57cec5SDimitry Andric 7220b57cec5SDimitry Andric void PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames() { 7230b57cec5SDimitry Andric m_trap_handlers.push_back(ConstString("_sigtramp")); 7240b57cec5SDimitry Andric } 7250b57cec5SDimitry Andric 7260b57cec5SDimitry Andric const UnixSignalsSP &PlatformRemoteGDBServer::GetRemoteUnixSignals() { 7270b57cec5SDimitry Andric if (!IsConnected()) 7280b57cec5SDimitry Andric return Platform::GetRemoteUnixSignals(); 7290b57cec5SDimitry Andric 7300b57cec5SDimitry Andric if (m_remote_signals_sp) 7310b57cec5SDimitry Andric return m_remote_signals_sp; 7320b57cec5SDimitry Andric 7330b57cec5SDimitry Andric // If packet not implemented or JSON failed to parse, we'll guess the signal 7340b57cec5SDimitry Andric // set based on the remote architecture. 7350b57cec5SDimitry Andric m_remote_signals_sp = UnixSignals::Create(GetRemoteSystemArchitecture()); 7360b57cec5SDimitry Andric 7370b57cec5SDimitry Andric StringExtractorGDBRemote response; 7380b57cec5SDimitry Andric auto result = m_gdb_client.SendPacketAndWaitForResponse("jSignalsInfo", 7390b57cec5SDimitry Andric response, false); 7400b57cec5SDimitry Andric 7410b57cec5SDimitry Andric if (result != decltype(result)::Success || 7420b57cec5SDimitry Andric response.GetResponseType() != response.eResponse) 7430b57cec5SDimitry Andric return m_remote_signals_sp; 7440b57cec5SDimitry Andric 7455ffd83dbSDimitry Andric auto object_sp = 7465ffd83dbSDimitry Andric StructuredData::ParseJSON(std::string(response.GetStringRef())); 7470b57cec5SDimitry Andric if (!object_sp || !object_sp->IsValid()) 7480b57cec5SDimitry Andric return m_remote_signals_sp; 7490b57cec5SDimitry Andric 7500b57cec5SDimitry Andric auto array_sp = object_sp->GetAsArray(); 7510b57cec5SDimitry Andric if (!array_sp || !array_sp->IsValid()) 7520b57cec5SDimitry Andric return m_remote_signals_sp; 7530b57cec5SDimitry Andric 7540b57cec5SDimitry Andric auto remote_signals_sp = std::make_shared<lldb_private::GDBRemoteSignals>(); 7550b57cec5SDimitry Andric 7560b57cec5SDimitry Andric bool done = array_sp->ForEach( 7570b57cec5SDimitry Andric [&remote_signals_sp](StructuredData::Object *object) -> bool { 7580b57cec5SDimitry Andric if (!object || !object->IsValid()) 7590b57cec5SDimitry Andric return false; 7600b57cec5SDimitry Andric 7610b57cec5SDimitry Andric auto dict = object->GetAsDictionary(); 7620b57cec5SDimitry Andric if (!dict || !dict->IsValid()) 7630b57cec5SDimitry Andric return false; 7640b57cec5SDimitry Andric 7650b57cec5SDimitry Andric // Signal number and signal name are required. 7660b57cec5SDimitry Andric int signo; 7670b57cec5SDimitry Andric if (!dict->GetValueForKeyAsInteger("signo", signo)) 7680b57cec5SDimitry Andric return false; 7690b57cec5SDimitry Andric 7700b57cec5SDimitry Andric llvm::StringRef name; 7710b57cec5SDimitry Andric if (!dict->GetValueForKeyAsString("name", name)) 7720b57cec5SDimitry Andric return false; 7730b57cec5SDimitry Andric 7740b57cec5SDimitry Andric // We can live without short_name, description, etc. 7750b57cec5SDimitry Andric bool suppress{false}; 7760b57cec5SDimitry Andric auto object_sp = dict->GetValueForKey("suppress"); 7770b57cec5SDimitry Andric if (object_sp && object_sp->IsValid()) 7780b57cec5SDimitry Andric suppress = object_sp->GetBooleanValue(); 7790b57cec5SDimitry Andric 7800b57cec5SDimitry Andric bool stop{false}; 7810b57cec5SDimitry Andric object_sp = dict->GetValueForKey("stop"); 7820b57cec5SDimitry Andric if (object_sp && object_sp->IsValid()) 7830b57cec5SDimitry Andric stop = object_sp->GetBooleanValue(); 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric bool notify{false}; 7860b57cec5SDimitry Andric object_sp = dict->GetValueForKey("notify"); 7870b57cec5SDimitry Andric if (object_sp && object_sp->IsValid()) 7880b57cec5SDimitry Andric notify = object_sp->GetBooleanValue(); 7890b57cec5SDimitry Andric 7900b57cec5SDimitry Andric std::string description{""}; 7910b57cec5SDimitry Andric object_sp = dict->GetValueForKey("description"); 7920b57cec5SDimitry Andric if (object_sp && object_sp->IsValid()) 7935ffd83dbSDimitry Andric description = std::string(object_sp->GetStringValue()); 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric remote_signals_sp->AddSignal(signo, name.str().c_str(), suppress, stop, 7960b57cec5SDimitry Andric notify, description.c_str()); 7970b57cec5SDimitry Andric return true; 7980b57cec5SDimitry Andric }); 7990b57cec5SDimitry Andric 8000b57cec5SDimitry Andric if (done) 8010b57cec5SDimitry Andric m_remote_signals_sp = std::move(remote_signals_sp); 8020b57cec5SDimitry Andric 8030b57cec5SDimitry Andric return m_remote_signals_sp; 8040b57cec5SDimitry Andric } 8050b57cec5SDimitry Andric 8060b57cec5SDimitry Andric std::string PlatformRemoteGDBServer::MakeGdbServerUrl( 8070b57cec5SDimitry Andric const std::string &platform_scheme, const std::string &platform_hostname, 8080b57cec5SDimitry Andric uint16_t port, const char *socket_name) { 8090b57cec5SDimitry Andric const char *override_scheme = 8100b57cec5SDimitry Andric getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME"); 8110b57cec5SDimitry Andric const char *override_hostname = 8120b57cec5SDimitry Andric getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME"); 8130b57cec5SDimitry Andric const char *port_offset_c_str = 8140b57cec5SDimitry Andric getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET"); 8150b57cec5SDimitry Andric int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0; 8160b57cec5SDimitry Andric 8170b57cec5SDimitry Andric return MakeUrl(override_scheme ? override_scheme : platform_scheme.c_str(), 8180b57cec5SDimitry Andric override_hostname ? override_hostname 8190b57cec5SDimitry Andric : platform_hostname.c_str(), 8200b57cec5SDimitry Andric port + port_offset, socket_name); 8210b57cec5SDimitry Andric } 8220b57cec5SDimitry Andric 8230b57cec5SDimitry Andric std::string PlatformRemoteGDBServer::MakeUrl(const char *scheme, 8240b57cec5SDimitry Andric const char *hostname, 8250b57cec5SDimitry Andric uint16_t port, const char *path) { 8260b57cec5SDimitry Andric StreamString result; 8270b57cec5SDimitry Andric result.Printf("%s://%s", scheme, hostname); 8280b57cec5SDimitry Andric if (port != 0) 8290b57cec5SDimitry Andric result.Printf(":%u", port); 8300b57cec5SDimitry Andric if (path) 8310b57cec5SDimitry Andric result.Write(path, strlen(path)); 8325ffd83dbSDimitry Andric return std::string(result.GetString()); 8330b57cec5SDimitry Andric } 8340b57cec5SDimitry Andric 8350b57cec5SDimitry Andric lldb::ProcessSP PlatformRemoteGDBServer::ConnectProcess( 8360b57cec5SDimitry Andric llvm::StringRef connect_url, llvm::StringRef plugin_name, 8370b57cec5SDimitry Andric lldb_private::Debugger &debugger, lldb_private::Target *target, 8380b57cec5SDimitry Andric lldb_private::Status &error) { 8390b57cec5SDimitry Andric if (!IsRemote() || !IsConnected()) { 8400b57cec5SDimitry Andric error.SetErrorString("Not connected to remote gdb server"); 8410b57cec5SDimitry Andric return nullptr; 8420b57cec5SDimitry Andric } 8430b57cec5SDimitry Andric return Platform::ConnectProcess(connect_url, plugin_name, debugger, target, 8440b57cec5SDimitry Andric error); 8450b57cec5SDimitry Andric } 8460b57cec5SDimitry Andric 8470b57cec5SDimitry Andric size_t PlatformRemoteGDBServer::ConnectToWaitingProcesses(Debugger &debugger, 8480b57cec5SDimitry Andric Status &error) { 8490b57cec5SDimitry Andric std::vector<std::string> connection_urls; 8500b57cec5SDimitry Andric GetPendingGdbServerList(connection_urls); 8510b57cec5SDimitry Andric 8520b57cec5SDimitry Andric for (size_t i = 0; i < connection_urls.size(); ++i) { 8530b57cec5SDimitry Andric ConnectProcess(connection_urls[i].c_str(), "", debugger, nullptr, error); 8540b57cec5SDimitry Andric if (error.Fail()) 8550b57cec5SDimitry Andric return i; // We already connected to i process succsessfully 8560b57cec5SDimitry Andric } 8570b57cec5SDimitry Andric return connection_urls.size(); 8580b57cec5SDimitry Andric } 8590b57cec5SDimitry Andric 8600b57cec5SDimitry Andric size_t PlatformRemoteGDBServer::GetPendingGdbServerList( 8610b57cec5SDimitry Andric std::vector<std::string> &connection_urls) { 8620b57cec5SDimitry Andric std::vector<std::pair<uint16_t, std::string>> remote_servers; 8630b57cec5SDimitry Andric m_gdb_client.QueryGDBServer(remote_servers); 8640b57cec5SDimitry Andric for (const auto &gdbserver : remote_servers) { 8650b57cec5SDimitry Andric const char *socket_name_cstr = 8660b57cec5SDimitry Andric gdbserver.second.empty() ? nullptr : gdbserver.second.c_str(); 8670b57cec5SDimitry Andric connection_urls.emplace_back( 8680b57cec5SDimitry Andric MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, 8690b57cec5SDimitry Andric gdbserver.first, socket_name_cstr)); 8700b57cec5SDimitry Andric } 8710b57cec5SDimitry Andric return connection_urls.size(); 8720b57cec5SDimitry Andric } 873