1 //===-- PlatformRemoteGDBServer.cpp ---------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "PlatformRemoteGDBServer.h"
10 #include "lldb/Host/Config.h"
12 #include "lldb/Breakpoint/BreakpointLocation.h"
13 #include "lldb/Core/Debugger.h"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/ModuleList.h"
16 #include "lldb/Core/ModuleSpec.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Host/ConnectionFileDescriptor.h"
19 #include "lldb/Host/Host.h"
20 #include "lldb/Host/HostInfo.h"
21 #include "lldb/Host/PosixApi.h"
22 #include "lldb/Target/Process.h"
23 #include "lldb/Target/Target.h"
24 #include "lldb/Utility/FileSpec.h"
25 #include "lldb/Utility/LLDBLog.h"
26 #include "lldb/Utility/Log.h"
27 #include "lldb/Utility/ProcessInfo.h"
28 #include "lldb/Utility/Status.h"
29 #include "lldb/Utility/StreamString.h"
30 #include "lldb/Utility/UriParser.h"
31 #include "llvm/ADT/StringSet.h"
32 #include "llvm/Support/FormatAdapters.h"
34 #include "Plugins/Process/Utility/GDBRemoteSignals.h"
35 #include "Plugins/Process/gdb-remote/ProcessGDBRemote.h"
40 using namespace lldb_private
;
41 using namespace lldb_private::platform_gdb_server
;
43 LLDB_PLUGIN_DEFINE_ADV(PlatformRemoteGDBServer
, PlatformGDB
)
45 static bool g_initialized
= false;
46 // UnixSignals does not store the signal names or descriptions itself.
47 // It holds onto StringRefs. Becaue we may get signal information dynamically
48 // from the remote, these strings need persistent storage client-side.
49 static std::mutex g_signal_string_mutex
;
50 static llvm::StringSet
<> g_signal_string_storage
;
52 void PlatformRemoteGDBServer::Initialize() {
53 Platform::Initialize();
57 PluginManager::RegisterPlugin(
58 PlatformRemoteGDBServer::GetPluginNameStatic(),
59 PlatformRemoteGDBServer::GetDescriptionStatic(),
60 PlatformRemoteGDBServer::CreateInstance
);
64 void PlatformRemoteGDBServer::Terminate() {
66 g_initialized
= false;
67 PluginManager::UnregisterPlugin(PlatformRemoteGDBServer::CreateInstance
);
70 Platform::Terminate();
73 PlatformSP
PlatformRemoteGDBServer::CreateInstance(bool force
,
74 const ArchSpec
*arch
) {
77 create
= !arch
->TripleVendorWasSpecified() && !arch
->TripleOSWasSpecified();
80 return PlatformSP(new PlatformRemoteGDBServer());
84 llvm::StringRef
PlatformRemoteGDBServer::GetDescriptionStatic() {
85 return "A platform that uses the GDB remote protocol as the communication "
89 llvm::StringRef
PlatformRemoteGDBServer::GetDescription() {
90 if (m_platform_description
.empty()) {
92 // Send the get description packet
96 if (!m_platform_description
.empty())
97 return m_platform_description
.c_str();
98 return GetDescriptionStatic();
101 bool PlatformRemoteGDBServer::GetModuleSpec(const FileSpec
&module_file_spec
,
102 const ArchSpec
&arch
,
103 ModuleSpec
&module_spec
) {
104 Log
*log
= GetLog(LLDBLog::Platform
);
106 const auto module_path
= module_file_spec
.GetPath(false);
108 if (!m_gdb_client_up
||
109 !m_gdb_client_up
->GetModuleInfo(module_file_spec
, arch
, module_spec
)) {
112 "PlatformRemoteGDBServer::%s - failed to get module info for %s:%s",
113 __FUNCTION__
, module_path
.c_str(),
114 arch
.GetTriple().getTriple().c_str());
120 module_spec
.Dump(stream
);
122 "PlatformRemoteGDBServer::%s - got module info for (%s:%s) : %s",
123 __FUNCTION__
, module_path
.c_str(),
124 arch
.GetTriple().getTriple().c_str(), stream
.GetData());
130 Status
PlatformRemoteGDBServer::GetFileWithUUID(const FileSpec
&platform_file
,
131 const UUID
*uuid_ptr
,
132 FileSpec
&local_file
) {
133 // Default to the local case
134 local_file
= platform_file
;
138 /// Default Constructor
139 PlatformRemoteGDBServer::PlatformRemoteGDBServer()
140 : Platform(/*is_host=*/false) {}
144 /// The destructor is virtual since this class is designed to be
145 /// inherited from by the plug-in instance.
146 PlatformRemoteGDBServer::~PlatformRemoteGDBServer() = default;
148 size_t PlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode(
149 Target
&target
, BreakpointSite
*bp_site
) {
150 // This isn't needed if the z/Z packets are supported in the GDB remote
151 // server. But we might need a packet to detect this.
155 bool PlatformRemoteGDBServer::GetRemoteOSVersion() {
157 m_os_version
= m_gdb_client_up
->GetOSVersion();
158 return !m_os_version
.empty();
161 std::optional
<std::string
> PlatformRemoteGDBServer::GetRemoteOSBuildString() {
162 if (!m_gdb_client_up
)
164 return m_gdb_client_up
->GetOSBuildString();
167 std::optional
<std::string
>
168 PlatformRemoteGDBServer::GetRemoteOSKernelDescription() {
169 if (!m_gdb_client_up
)
171 return m_gdb_client_up
->GetOSKernelDescription();
174 // Remote Platform subclasses need to override this function
175 ArchSpec
PlatformRemoteGDBServer::GetRemoteSystemArchitecture() {
176 if (!m_gdb_client_up
)
178 return m_gdb_client_up
->GetSystemArchitecture();
181 FileSpec
PlatformRemoteGDBServer::GetRemoteWorkingDirectory() {
183 Log
*log
= GetLog(LLDBLog::Platform
);
184 FileSpec working_dir
;
185 if (m_gdb_client_up
->GetWorkingDir(working_dir
) && log
)
187 "PlatformRemoteGDBServer::GetRemoteWorkingDirectory() -> '%s'",
188 working_dir
.GetPath().c_str());
191 return Platform::GetRemoteWorkingDirectory();
195 bool PlatformRemoteGDBServer::SetRemoteWorkingDirectory(
196 const FileSpec
&working_dir
) {
198 // Clear the working directory it case it doesn't get set correctly. This
199 // will for use to re-read it
200 Log
*log
= GetLog(LLDBLog::Platform
);
201 LLDB_LOGF(log
, "PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')",
202 working_dir
.GetPath().c_str());
203 return m_gdb_client_up
->SetWorkingDir(working_dir
) == 0;
205 return Platform::SetRemoteWorkingDirectory(working_dir
);
208 bool PlatformRemoteGDBServer::IsConnected() const {
209 if (m_gdb_client_up
) {
210 assert(m_gdb_client_up
->IsConnected());
216 Status
PlatformRemoteGDBServer::ConnectRemote(Args
&args
) {
219 return Status::FromErrorStringWithFormat(
220 "the platform is already connected to '%s', "
221 "execute 'platform disconnect' to close the "
222 "current connection",
225 if (args
.GetArgumentCount() != 1)
226 return Status::FromErrorString(
227 "\"platform connect\" takes a single argument: <connect-url>");
229 const char *url
= args
.GetArgumentAtIndex(0);
231 return Status::FromErrorString("URL is null.");
233 std::optional
<URI
> parsed_url
= URI::Parse(url
);
235 return Status::FromErrorStringWithFormat("Invalid URL: %s", url
);
237 // We're going to reuse the hostname when we connect to the debugserver.
238 m_platform_scheme
= parsed_url
->scheme
.str();
239 m_platform_hostname
= parsed_url
->hostname
.str();
242 std::make_unique
<process_gdb_remote::GDBRemoteCommunicationClient
>();
243 client_up
->SetPacketTimeout(
244 process_gdb_remote::ProcessGDBRemote::GetPacketTimeout());
245 client_up
->SetConnection(std::make_unique
<ConnectionFileDescriptor
>());
246 client_up
->Connect(url
, &error
);
251 if (client_up
->HandshakeWithServer(&error
)) {
252 m_gdb_client_up
= std::move(client_up
);
253 m_gdb_client_up
->GetHostInfo();
254 // If a working directory was set prior to connecting, send it down
257 m_gdb_client_up
->SetWorkingDir(m_working_dir
);
259 m_supported_architectures
.clear();
260 ArchSpec remote_arch
= m_gdb_client_up
->GetSystemArchitecture();
262 m_supported_architectures
.push_back(remote_arch
);
263 if (remote_arch
.GetTriple().isArch64Bit())
264 m_supported_architectures
.push_back(
265 ArchSpec(remote_arch
.GetTriple().get32BitArchVariant()));
268 client_up
->Disconnect();
270 error
= Status::FromErrorString("handshake failed");
275 Status
PlatformRemoteGDBServer::DisconnectRemote() {
277 m_gdb_client_up
.reset();
278 m_remote_signals_sp
.reset();
282 const char *PlatformRemoteGDBServer::GetHostname() {
284 m_gdb_client_up
->GetHostname(m_hostname
);
285 if (m_hostname
.empty())
287 return m_hostname
.c_str();
290 std::optional
<std::string
>
291 PlatformRemoteGDBServer::DoGetUserName(UserIDResolver::id_t uid
) {
293 if (m_gdb_client_up
&& m_gdb_client_up
->GetUserName(uid
, name
))
294 return std::move(name
);
298 std::optional
<std::string
>
299 PlatformRemoteGDBServer::DoGetGroupName(UserIDResolver::id_t gid
) {
301 if (m_gdb_client_up
&& m_gdb_client_up
->GetGroupName(gid
, name
))
302 return std::move(name
);
306 uint32_t PlatformRemoteGDBServer::FindProcesses(
307 const ProcessInstanceInfoMatch
&match_info
,
308 ProcessInstanceInfoList
&process_infos
) {
310 return m_gdb_client_up
->FindProcesses(match_info
, process_infos
);
314 bool PlatformRemoteGDBServer::GetProcessInfo(
315 lldb::pid_t pid
, ProcessInstanceInfo
&process_info
) {
317 return m_gdb_client_up
->GetProcessInfo(pid
, process_info
);
321 Status
PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo
&launch_info
) {
322 Log
*log
= GetLog(LLDBLog::Platform
);
325 LLDB_LOGF(log
, "PlatformRemoteGDBServer::%s() called", __FUNCTION__
);
328 return Status::FromErrorStringWithFormat("Not connected.");
329 auto num_file_actions
= launch_info
.GetNumFileActions();
330 for (decltype(num_file_actions
) i
= 0; i
< num_file_actions
; ++i
) {
331 const auto file_action
= launch_info
.GetFileActionAtIndex(i
);
332 if (file_action
->GetAction() != FileAction::eFileActionOpen
)
334 switch (file_action
->GetFD()) {
336 m_gdb_client_up
->SetSTDIN(file_action
->GetFileSpec());
339 m_gdb_client_up
->SetSTDOUT(file_action
->GetFileSpec());
342 m_gdb_client_up
->SetSTDERR(file_action
->GetFileSpec());
347 m_gdb_client_up
->SetDisableASLR(
348 launch_info
.GetFlags().Test(eLaunchFlagDisableASLR
));
349 m_gdb_client_up
->SetDetachOnError(
350 launch_info
.GetFlags().Test(eLaunchFlagDetachOnError
));
352 FileSpec working_dir
= launch_info
.GetWorkingDirectory();
354 m_gdb_client_up
->SetWorkingDir(working_dir
);
357 // Send the environment and the program + arguments after we connect
358 m_gdb_client_up
->SendEnvironment(launch_info
.GetEnvironment());
360 ArchSpec arch_spec
= launch_info
.GetArchitecture();
361 const char *arch_triple
= arch_spec
.GetTriple().str().c_str();
363 m_gdb_client_up
->SendLaunchArchPacket(arch_triple
);
366 "PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'",
367 __FUNCTION__
, arch_triple
? arch_triple
: "<NULL>");
370 // Scope for the scoped timeout object
371 process_gdb_remote::GDBRemoteCommunication::ScopedTimeout
timeout(
372 *m_gdb_client_up
, std::chrono::seconds(5));
373 // Since we can't send argv0 separate from the executable path, we need to
374 // make sure to use the actual executable path found in the launch_info...
375 Args args
= launch_info
.GetArguments();
376 if (FileSpec exe_file
= launch_info
.GetExecutableFile())
377 args
.ReplaceArgumentAtIndex(0, exe_file
.GetPath(false));
378 if (llvm::Error err
= m_gdb_client_up
->LaunchProcess(args
)) {
379 error
= Status::FromErrorStringWithFormatv(
380 "Cannot launch '{0}': {1}", args
.GetArgumentAtIndex(0),
381 llvm::fmt_consume(std::move(err
)));
386 const auto pid
= m_gdb_client_up
->GetCurrentProcessID(false);
387 if (pid
!= LLDB_INVALID_PROCESS_ID
) {
388 launch_info
.SetProcessID(pid
);
390 "PlatformRemoteGDBServer::%s() pid %" PRIu64
391 " launched successfully",
395 "PlatformRemoteGDBServer::%s() launch succeeded but we "
396 "didn't get a valid process id back!",
398 error
= Status::FromErrorString("failed to get PID");
403 Status
PlatformRemoteGDBServer::KillProcess(const lldb::pid_t pid
) {
404 if (!KillSpawnedProcess(pid
))
405 return Status::FromErrorStringWithFormat(
406 "failed to kill remote spawned process");
411 PlatformRemoteGDBServer::DebugProcess(ProcessLaunchInfo
&launch_info
,
412 Debugger
&debugger
, Target
&target
,
414 lldb::ProcessSP process_sp
;
417 lldb::pid_t debugserver_pid
= LLDB_INVALID_PROCESS_ID
;
418 std::string connect_url
;
419 if (!LaunchGDBServer(debugserver_pid
, connect_url
)) {
420 error
= Status::FromErrorStringWithFormat(
421 "unable to launch a GDB server on '%s'", GetHostname());
423 // The darwin always currently uses the GDB remote debugger plug-in
424 // so even when debugging locally we are debugging remotely!
425 process_sp
= target
.CreateProcess(launch_info
.GetListener(),
426 "gdb-remote", nullptr, true);
429 process_sp
->HijackProcessEvents(launch_info
.GetHijackListener());
430 process_sp
->SetShadowListener(launch_info
.GetShadowListener());
432 error
= process_sp
->ConnectRemote(connect_url
.c_str());
433 // Retry the connect remote one time...
435 error
= process_sp
->ConnectRemote(connect_url
.c_str());
437 error
= process_sp
->Launch(launch_info
);
438 else if (debugserver_pid
!= LLDB_INVALID_PROCESS_ID
) {
439 printf("error: connect remote failed (%s)\n", error
.AsCString());
440 KillSpawnedProcess(debugserver_pid
);
445 error
= Status::FromErrorString("not connected to remote gdb server");
451 bool PlatformRemoteGDBServer::LaunchGDBServer(lldb::pid_t
&pid
,
452 std::string
&connect_url
) {
453 assert(IsConnected());
455 ArchSpec remote_arch
= GetRemoteSystemArchitecture();
456 llvm::Triple
&remote_triple
= remote_arch
.GetTriple();
459 std::string socket_name
;
460 bool launch_result
= false;
461 if (remote_triple
.getVendor() == llvm::Triple::Apple
&&
462 remote_triple
.getOS() == llvm::Triple::IOS
) {
463 // When remote debugging to iOS, we use a USB mux that always talks to
464 // localhost, so we will need the remote debugserver to accept connections
465 // only from localhost, no matter what our current hostname is
467 m_gdb_client_up
->LaunchGDBServer("127.0.0.1", pid
, port
, socket_name
);
469 // All other hosts should use their actual hostname
471 m_gdb_client_up
->LaunchGDBServer(nullptr, pid
, port
, socket_name
);
478 MakeGdbServerUrl(m_platform_scheme
, m_platform_hostname
, port
,
479 (socket_name
.empty()) ? nullptr : socket_name
.c_str());
483 bool PlatformRemoteGDBServer::KillSpawnedProcess(lldb::pid_t pid
) {
484 assert(IsConnected());
485 return m_gdb_client_up
->KillSpawnedProcess(pid
);
488 lldb::ProcessSP
PlatformRemoteGDBServer::Attach(
489 ProcessAttachInfo
&attach_info
, Debugger
&debugger
,
490 Target
*target
, // Can be NULL, if NULL create a new target, else use
493 lldb::ProcessSP process_sp
;
496 lldb::pid_t debugserver_pid
= LLDB_INVALID_PROCESS_ID
;
497 std::string connect_url
;
498 if (!LaunchGDBServer(debugserver_pid
, connect_url
)) {
499 error
= Status::FromErrorStringWithFormat(
500 "unable to launch a GDB server on '%s'", GetHostname());
502 if (target
== nullptr) {
503 TargetSP new_target_sp
;
505 error
= debugger
.GetTargetList().CreateTarget(
506 debugger
, "", "", eLoadDependentsNo
, nullptr, new_target_sp
);
507 target
= new_target_sp
.get();
511 if (target
&& error
.Success()) {
512 // The darwin always currently uses the GDB remote debugger plug-in
513 // so even when debugging locally we are debugging remotely!
515 target
->CreateProcess(attach_info
.GetListenerForProcess(debugger
),
516 "gdb-remote", nullptr, true);
518 error
= process_sp
->ConnectRemote(connect_url
.c_str());
519 if (error
.Success()) {
520 ListenerSP listener_sp
= attach_info
.GetHijackListener();
522 process_sp
->HijackProcessEvents(listener_sp
);
523 process_sp
->SetShadowListener(attach_info
.GetShadowListener());
524 error
= process_sp
->Attach(attach_info
);
527 if (error
.Fail() && debugserver_pid
!= LLDB_INVALID_PROCESS_ID
) {
528 KillSpawnedProcess(debugserver_pid
);
534 error
= Status::FromErrorString("not connected to remote gdb server");
540 Status
PlatformRemoteGDBServer::MakeDirectory(const FileSpec
&file_spec
,
543 return Status::FromErrorStringWithFormat("Not connected.");
544 Status error
= m_gdb_client_up
->MakeDirectory(file_spec
, mode
);
545 Log
*log
= GetLog(LLDBLog::Platform
);
547 "PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) "
549 file_spec
.GetPath().c_str(), mode
, error
.GetError(),
554 Status
PlatformRemoteGDBServer::GetFilePermissions(const FileSpec
&file_spec
,
555 uint32_t &file_permissions
) {
557 return Status::FromErrorStringWithFormat("Not connected.");
559 m_gdb_client_up
->GetFilePermissions(file_spec
, file_permissions
);
560 Log
*log
= GetLog(LLDBLog::Platform
);
562 "PlatformRemoteGDBServer::GetFilePermissions(path='%s', "
563 "file_permissions=%o) error = %u (%s)",
564 file_spec
.GetPath().c_str(), file_permissions
, error
.GetError(),
569 Status
PlatformRemoteGDBServer::SetFilePermissions(const FileSpec
&file_spec
,
570 uint32_t file_permissions
) {
572 return Status::FromErrorStringWithFormat("Not connected.");
574 m_gdb_client_up
->SetFilePermissions(file_spec
, file_permissions
);
575 Log
*log
= GetLog(LLDBLog::Platform
);
577 "PlatformRemoteGDBServer::SetFilePermissions(path='%s', "
578 "file_permissions=%o) error = %u (%s)",
579 file_spec
.GetPath().c_str(), file_permissions
, error
.GetError(),
584 lldb::user_id_t
PlatformRemoteGDBServer::OpenFile(const FileSpec
&file_spec
,
585 File::OpenOptions flags
,
589 return m_gdb_client_up
->OpenFile(file_spec
, flags
, mode
, error
);
590 return LLDB_INVALID_UID
;
593 bool PlatformRemoteGDBServer::CloseFile(lldb::user_id_t fd
, Status
&error
) {
595 return m_gdb_client_up
->CloseFile(fd
, error
);
596 error
= Status::FromErrorStringWithFormat("Not connected.");
601 PlatformRemoteGDBServer::GetFileSize(const FileSpec
&file_spec
) {
603 return m_gdb_client_up
->GetFileSize(file_spec
);
604 return LLDB_INVALID_UID
;
607 void PlatformRemoteGDBServer::AutoCompleteDiskFileOrDirectory(
608 CompletionRequest
&request
, bool only_dir
) {
610 m_gdb_client_up
->AutoCompleteDiskFileOrDirectory(request
, only_dir
);
613 uint64_t PlatformRemoteGDBServer::ReadFile(lldb::user_id_t fd
, uint64_t offset
,
614 void *dst
, uint64_t dst_len
,
617 return m_gdb_client_up
->ReadFile(fd
, offset
, dst
, dst_len
, error
);
618 error
= Status::FromErrorStringWithFormat("Not connected.");
622 uint64_t PlatformRemoteGDBServer::WriteFile(lldb::user_id_t fd
, uint64_t offset
,
623 const void *src
, uint64_t src_len
,
626 return m_gdb_client_up
->WriteFile(fd
, offset
, src
, src_len
, error
);
627 error
= Status::FromErrorStringWithFormat("Not connected.");
631 Status
PlatformRemoteGDBServer::PutFile(const FileSpec
&source
,
632 const FileSpec
&destination
,
633 uint32_t uid
, uint32_t gid
) {
634 return Platform::PutFile(source
, destination
, uid
, gid
);
637 Status
PlatformRemoteGDBServer::CreateSymlink(
638 const FileSpec
&src
, // The name of the link is in src
639 const FileSpec
&dst
) // The symlink points to dst
642 return Status::FromErrorStringWithFormat("Not connected.");
643 Status error
= m_gdb_client_up
->CreateSymlink(src
, dst
);
644 Log
*log
= GetLog(LLDBLog::Platform
);
646 "PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') "
648 src
.GetPath().c_str(), dst
.GetPath().c_str(), error
.GetError(),
653 Status
PlatformRemoteGDBServer::Unlink(const FileSpec
&file_spec
) {
655 return Status::FromErrorStringWithFormat("Not connected.");
656 Status error
= m_gdb_client_up
->Unlink(file_spec
);
657 Log
*log
= GetLog(LLDBLog::Platform
);
658 LLDB_LOGF(log
, "PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)",
659 file_spec
.GetPath().c_str(), error
.GetError(), error
.AsCString());
663 bool PlatformRemoteGDBServer::GetFileExists(const FileSpec
&file_spec
) {
665 return m_gdb_client_up
->GetFileExists(file_spec
);
669 Status
PlatformRemoteGDBServer::RunShellCommand(
670 llvm::StringRef shell
, llvm::StringRef command
,
672 working_dir
, // Pass empty FileSpec to use the current working directory
673 int *status_ptr
, // Pass NULL if you don't want the process exit status
674 int *signo_ptr
, // Pass NULL if you don't want the signal that caused the
677 *command_output
, // Pass NULL if you don't want the command output
678 const Timeout
<std::micro
> &timeout
) {
680 return Status::FromErrorStringWithFormat("Not connected.");
681 return m_gdb_client_up
->RunShellCommand(command
, working_dir
, status_ptr
,
682 signo_ptr
, command_output
, timeout
);
685 llvm::ErrorOr
<llvm::MD5::MD5Result
>
686 PlatformRemoteGDBServer::CalculateMD5(const FileSpec
&file_spec
) {
688 return std::make_error_code(std::errc::not_connected
);
690 return m_gdb_client_up
->CalculateMD5(file_spec
);
693 void PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames() {
694 m_trap_handlers
.push_back(ConstString("_sigtramp"));
697 const UnixSignalsSP
&PlatformRemoteGDBServer::GetRemoteUnixSignals() {
699 return Platform::GetRemoteUnixSignals();
701 if (m_remote_signals_sp
)
702 return m_remote_signals_sp
;
704 // If packet not implemented or JSON failed to parse, we'll guess the signal
705 // set based on the remote architecture.
706 m_remote_signals_sp
= UnixSignals::Create(GetRemoteSystemArchitecture());
708 StringExtractorGDBRemote response
;
710 m_gdb_client_up
->SendPacketAndWaitForResponse("jSignalsInfo", response
);
712 if (result
!= decltype(result
)::Success
||
713 response
.GetResponseType() != response
.eResponse
)
714 return m_remote_signals_sp
;
716 auto object_sp
= StructuredData::ParseJSON(response
.GetStringRef());
717 if (!object_sp
|| !object_sp
->IsValid())
718 return m_remote_signals_sp
;
720 auto array_sp
= object_sp
->GetAsArray();
721 if (!array_sp
|| !array_sp
->IsValid())
722 return m_remote_signals_sp
;
724 auto remote_signals_sp
= std::make_shared
<lldb_private::GDBRemoteSignals
>();
726 bool done
= array_sp
->ForEach(
727 [&remote_signals_sp
](StructuredData::Object
*object
) -> bool {
728 if (!object
|| !object
->IsValid())
731 auto dict
= object
->GetAsDictionary();
732 if (!dict
|| !dict
->IsValid())
735 // Signal number and signal name are required.
737 if (!dict
->GetValueForKeyAsInteger("signo", signo
))
740 llvm::StringRef name
;
741 if (!dict
->GetValueForKeyAsString("name", name
))
744 // We can live without short_name, description, etc.
745 bool suppress
{false};
746 auto object_sp
= dict
->GetValueForKey("suppress");
747 if (object_sp
&& object_sp
->IsValid())
748 suppress
= object_sp
->GetBooleanValue();
751 object_sp
= dict
->GetValueForKey("stop");
752 if (object_sp
&& object_sp
->IsValid())
753 stop
= object_sp
->GetBooleanValue();
756 object_sp
= dict
->GetValueForKey("notify");
757 if (object_sp
&& object_sp
->IsValid())
758 notify
= object_sp
->GetBooleanValue();
760 std::string description
;
761 object_sp
= dict
->GetValueForKey("description");
762 if (object_sp
&& object_sp
->IsValid())
763 description
= std::string(object_sp
->GetStringValue());
765 llvm::StringRef name_backed
, description_backed
;
767 std::lock_guard
<std::mutex
> guard(g_signal_string_mutex
);
769 g_signal_string_storage
.insert(name
).first
->getKeyData();
770 if (!description
.empty())
772 g_signal_string_storage
.insert(description
).first
->getKeyData();
775 remote_signals_sp
->AddSignal(signo
, name_backed
, suppress
, stop
, notify
,
781 m_remote_signals_sp
= std::move(remote_signals_sp
);
783 return m_remote_signals_sp
;
786 std::string
PlatformRemoteGDBServer::MakeGdbServerUrl(
787 const std::string
&platform_scheme
, const std::string
&platform_hostname
,
788 uint16_t port
, const char *socket_name
) {
789 const char *override_scheme
=
790 getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME");
791 const char *override_hostname
=
792 getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME");
793 const char *port_offset_c_str
=
794 getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET");
795 int port_offset
= port_offset_c_str
? ::atoi(port_offset_c_str
) : 0;
797 return MakeUrl(override_scheme
? override_scheme
: platform_scheme
.c_str(),
798 override_hostname
? override_hostname
799 : platform_hostname
.c_str(),
800 port
+ port_offset
, socket_name
);
803 std::string
PlatformRemoteGDBServer::MakeUrl(const char *scheme
,
804 const char *hostname
,
805 uint16_t port
, const char *path
) {
807 result
.Printf("%s://[%s]", scheme
, hostname
);
809 result
.Printf(":%u", port
);
811 result
.Write(path
, strlen(path
));
812 return std::string(result
.GetString());
815 size_t PlatformRemoteGDBServer::ConnectToWaitingProcesses(Debugger
&debugger
,
817 std::vector
<std::string
> connection_urls
;
818 GetPendingGdbServerList(connection_urls
);
820 for (size_t i
= 0; i
< connection_urls
.size(); ++i
) {
821 ConnectProcess(connection_urls
[i
].c_str(), "gdb-remote", debugger
, nullptr, error
);
823 return i
; // We already connected to i process successfully
825 return connection_urls
.size();
828 size_t PlatformRemoteGDBServer::GetPendingGdbServerList(
829 std::vector
<std::string
> &connection_urls
) {
830 std::vector
<std::pair
<uint16_t, std::string
>> remote_servers
;
833 m_gdb_client_up
->QueryGDBServer(remote_servers
);
834 for (const auto &gdbserver
: remote_servers
) {
835 const char *socket_name_cstr
=
836 gdbserver
.second
.empty() ? nullptr : gdbserver
.second
.c_str();
837 connection_urls
.emplace_back(
838 MakeGdbServerUrl(m_platform_scheme
, m_platform_hostname
,
839 gdbserver
.first
, socket_name_cstr
));
841 return connection_urls
.size();