1 //===-- PlatformRemoteGDBServer.cpp -----------------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "PlatformRemoteGDBServer.h"
10 #include "lldb/Host/Config.h"
11 
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/Core/StreamFile.h"
19 #include "lldb/Host/ConnectionFileDescriptor.h"
20 #include "lldb/Host/Host.h"
21 #include "lldb/Host/HostInfo.h"
22 #include "lldb/Host/PosixApi.h"
23 #include "lldb/Target/Process.h"
24 #include "lldb/Target/Target.h"
25 #include "lldb/Utility/FileSpec.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 
32 #include "Plugins/Process/Utility/GDBRemoteSignals.h"
33 
34 using namespace lldb;
35 using namespace lldb_private;
36 using namespace lldb_private::platform_gdb_server;
37 
38 static bool g_initialized = false;
39 
40 void PlatformRemoteGDBServer::Initialize() {
41   Platform::Initialize();
42 
43   if (!g_initialized) {
44     g_initialized = true;
45     PluginManager::RegisterPlugin(
46         PlatformRemoteGDBServer::GetPluginNameStatic(),
47         PlatformRemoteGDBServer::GetDescriptionStatic(),
48         PlatformRemoteGDBServer::CreateInstance);
49   }
50 }
51 
52 void PlatformRemoteGDBServer::Terminate() {
53   if (g_initialized) {
54     g_initialized = false;
55     PluginManager::UnregisterPlugin(PlatformRemoteGDBServer::CreateInstance);
56   }
57 
58   Platform::Terminate();
59 }
60 
61 PlatformSP PlatformRemoteGDBServer::CreateInstance(bool force,
62                                                    const ArchSpec *arch) {
63   bool create = force;
64   if (!create) {
65     create = !arch->TripleVendorWasSpecified() && !arch->TripleOSWasSpecified();
66   }
67   if (create)
68     return PlatformSP(new PlatformRemoteGDBServer());
69   return PlatformSP();
70 }
71 
72 ConstString PlatformRemoteGDBServer::GetPluginNameStatic() {
73   static ConstString g_name("remote-gdb-server");
74   return g_name;
75 }
76 
77 const char *PlatformRemoteGDBServer::GetDescriptionStatic() {
78   return "A platform that uses the GDB remote protocol as the communication "
79          "transport.";
80 }
81 
82 const char *PlatformRemoteGDBServer::GetDescription() {
83   if (m_platform_description.empty()) {
84     if (IsConnected()) {
85       // Send the get description packet
86     }
87   }
88 
89   if (!m_platform_description.empty())
90     return m_platform_description.c_str();
91   return GetDescriptionStatic();
92 }
93 
94 Status PlatformRemoteGDBServer::ResolveExecutable(
95     const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp,
96     const FileSpecList *module_search_paths_ptr) {
97   // copied from PlatformRemoteiOS
98 
99   Status error;
100   // Nothing special to do here, just use the actual file and architecture
101 
102   ModuleSpec resolved_module_spec(module_spec);
103 
104   // Resolve any executable within an apk on Android?
105   // Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
106 
107   if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()) ||
108       module_spec.GetUUID().IsValid()) {
109     if (resolved_module_spec.GetArchitecture().IsValid() ||
110         resolved_module_spec.GetUUID().IsValid()) {
111       error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
112                                           module_search_paths_ptr, NULL, NULL);
113 
114       if (exe_module_sp && exe_module_sp->GetObjectFile())
115         return error;
116       exe_module_sp.reset();
117     }
118     // No valid architecture was specified or the exact arch wasn't found so
119     // ask the platform for the architectures that we should be using (in the
120     // correct order) and see if we can find a match that way
121     StreamString arch_names;
122     for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
123              idx, resolved_module_spec.GetArchitecture());
124          ++idx) {
125       error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
126                                           module_search_paths_ptr, NULL, NULL);
127       // Did we find an executable using one of the
128       if (error.Success()) {
129         if (exe_module_sp && exe_module_sp->GetObjectFile())
130           break;
131         else
132           error.SetErrorToGenericError();
133       }
134 
135       if (idx > 0)
136         arch_names.PutCString(", ");
137       arch_names.PutCString(
138           resolved_module_spec.GetArchitecture().GetArchitectureName());
139     }
140 
141     if (error.Fail() || !exe_module_sp) {
142       if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) {
143         error.SetErrorStringWithFormat(
144             "'%s' doesn't contain any '%s' platform architectures: %s",
145             resolved_module_spec.GetFileSpec().GetPath().c_str(),
146             GetPluginName().GetCString(), arch_names.GetData());
147       } else {
148         error.SetErrorStringWithFormat(
149             "'%s' is not readable",
150             resolved_module_spec.GetFileSpec().GetPath().c_str());
151       }
152     }
153   } else {
154     error.SetErrorStringWithFormat(
155         "'%s' does not exist",
156         resolved_module_spec.GetFileSpec().GetPath().c_str());
157   }
158 
159   return error;
160 }
161 
162 bool PlatformRemoteGDBServer::GetModuleSpec(const FileSpec &module_file_spec,
163                                             const ArchSpec &arch,
164                                             ModuleSpec &module_spec) {
165   Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
166 
167   const auto module_path = module_file_spec.GetPath(false);
168 
169   if (!m_gdb_client.GetModuleInfo(module_file_spec, arch, module_spec)) {
170     if (log)
171       log->Printf(
172           "PlatformRemoteGDBServer::%s - failed to get module info for %s:%s",
173           __FUNCTION__, module_path.c_str(),
174           arch.GetTriple().getTriple().c_str());
175     return false;
176   }
177 
178   if (log) {
179     StreamString stream;
180     module_spec.Dump(stream);
181     log->Printf(
182         "PlatformRemoteGDBServer::%s - got module info for (%s:%s) : %s",
183         __FUNCTION__, module_path.c_str(), arch.GetTriple().getTriple().c_str(),
184         stream.GetData());
185   }
186 
187   return true;
188 }
189 
190 Status PlatformRemoteGDBServer::GetFileWithUUID(const FileSpec &platform_file,
191                                                 const UUID *uuid_ptr,
192                                                 FileSpec &local_file) {
193   // Default to the local case
194   local_file = platform_file;
195   return Status();
196 }
197 
198 //------------------------------------------------------------------
199 /// Default Constructor
200 //------------------------------------------------------------------
201 PlatformRemoteGDBServer::PlatformRemoteGDBServer()
202     : Platform(false), // This is a remote platform
203       m_gdb_client() {}
204 
205 //------------------------------------------------------------------
206 /// Destructor.
207 ///
208 /// The destructor is virtual since this class is designed to be
209 /// inherited from by the plug-in instance.
210 //------------------------------------------------------------------
211 PlatformRemoteGDBServer::~PlatformRemoteGDBServer() {}
212 
213 bool PlatformRemoteGDBServer::GetSupportedArchitectureAtIndex(uint32_t idx,
214                                                               ArchSpec &arch) {
215   ArchSpec remote_arch = m_gdb_client.GetSystemArchitecture();
216 
217   if (idx == 0) {
218     arch = remote_arch;
219     return arch.IsValid();
220   } else if (idx == 1 && remote_arch.IsValid() &&
221              remote_arch.GetTriple().isArch64Bit()) {
222     arch.SetTriple(remote_arch.GetTriple().get32BitArchVariant());
223     return arch.IsValid();
224   }
225   return false;
226 }
227 
228 size_t PlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode(
229     Target &target, BreakpointSite *bp_site) {
230   // This isn't needed if the z/Z packets are supported in the GDB remote
231   // server. But we might need a packet to detect this.
232   return 0;
233 }
234 
235 bool PlatformRemoteGDBServer::GetRemoteOSVersion() {
236   m_os_version = m_gdb_client.GetOSVersion();
237   return !m_os_version.empty();
238 }
239 
240 bool PlatformRemoteGDBServer::GetRemoteOSBuildString(std::string &s) {
241   return m_gdb_client.GetOSBuildString(s);
242 }
243 
244 bool PlatformRemoteGDBServer::GetRemoteOSKernelDescription(std::string &s) {
245   return m_gdb_client.GetOSKernelDescription(s);
246 }
247 
248 // Remote Platform subclasses need to override this function
249 ArchSpec PlatformRemoteGDBServer::GetRemoteSystemArchitecture() {
250   return m_gdb_client.GetSystemArchitecture();
251 }
252 
253 FileSpec PlatformRemoteGDBServer::GetRemoteWorkingDirectory() {
254   if (IsConnected()) {
255     Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
256     FileSpec working_dir;
257     if (m_gdb_client.GetWorkingDir(working_dir) && log)
258       log->Printf(
259           "PlatformRemoteGDBServer::GetRemoteWorkingDirectory() -> '%s'",
260           working_dir.GetCString());
261     return working_dir;
262   } else {
263     return Platform::GetRemoteWorkingDirectory();
264   }
265 }
266 
267 bool PlatformRemoteGDBServer::SetRemoteWorkingDirectory(
268     const FileSpec &working_dir) {
269   if (IsConnected()) {
270     // Clear the working directory it case it doesn't get set correctly. This
271     // will for use to re-read it
272     Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
273     if (log)
274       log->Printf("PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')",
275                   working_dir.GetCString());
276     return m_gdb_client.SetWorkingDir(working_dir) == 0;
277   } else
278     return Platform::SetRemoteWorkingDirectory(working_dir);
279 }
280 
281 bool PlatformRemoteGDBServer::IsConnected() const {
282   return m_gdb_client.IsConnected();
283 }
284 
285 Status PlatformRemoteGDBServer::ConnectRemote(Args &args) {
286   Status error;
287   if (IsConnected()) {
288     error.SetErrorStringWithFormat("the platform is already connected to '%s', "
289                                    "execute 'platform disconnect' to close the "
290                                    "current connection",
291                                    GetHostname());
292   } else {
293     if (args.GetArgumentCount() == 1) {
294       m_gdb_client.SetConnection(new ConnectionFileDescriptor());
295       // we're going to reuse the hostname when we connect to the debugserver
296       int port;
297       std::string path;
298       const char *url = args.GetArgumentAtIndex(0);
299       if (!url)
300         return Status("URL is null.");
301       llvm::StringRef scheme, hostname, pathname;
302       if (!UriParser::Parse(url, scheme, hostname, port, pathname))
303         return Status("Invalid URL: %s", url);
304       m_platform_scheme = scheme;
305       m_platform_hostname = hostname;
306       path = pathname;
307 
308       const ConnectionStatus status = m_gdb_client.Connect(url, &error);
309       if (status == eConnectionStatusSuccess) {
310         if (m_gdb_client.HandshakeWithServer(&error)) {
311           m_gdb_client.GetHostInfo();
312           // If a working directory was set prior to connecting, send it down
313           // now
314           if (m_working_dir)
315             m_gdb_client.SetWorkingDir(m_working_dir);
316         } else {
317           m_gdb_client.Disconnect();
318           if (error.Success())
319             error.SetErrorString("handshake failed");
320         }
321       }
322     } else {
323       error.SetErrorString(
324           "\"platform connect\" takes a single argument: <connect-url>");
325     }
326   }
327   return error;
328 }
329 
330 Status PlatformRemoteGDBServer::DisconnectRemote() {
331   Status error;
332   m_gdb_client.Disconnect(&error);
333   m_remote_signals_sp.reset();
334   return error;
335 }
336 
337 const char *PlatformRemoteGDBServer::GetHostname() {
338   m_gdb_client.GetHostname(m_name);
339   if (m_name.empty())
340     return NULL;
341   return m_name.c_str();
342 }
343 
344 llvm::Optional<std::string>
345 PlatformRemoteGDBServer::DoGetUserName(UserIDResolver::id_t uid) {
346   std::string name;
347   if (m_gdb_client.GetUserName(uid, name))
348     return std::move(name);
349   return llvm::None;
350 }
351 
352 llvm::Optional<std::string>
353 PlatformRemoteGDBServer::DoGetGroupName(UserIDResolver::id_t gid) {
354   std::string name;
355   if (m_gdb_client.GetGroupName(gid, name))
356     return std::move(name);
357   return llvm::None;
358 }
359 
360 uint32_t PlatformRemoteGDBServer::FindProcesses(
361     const ProcessInstanceInfoMatch &match_info,
362     ProcessInstanceInfoList &process_infos) {
363   return m_gdb_client.FindProcesses(match_info, process_infos);
364 }
365 
366 bool PlatformRemoteGDBServer::GetProcessInfo(
367     lldb::pid_t pid, ProcessInstanceInfo &process_info) {
368   return m_gdb_client.GetProcessInfo(pid, process_info);
369 }
370 
371 Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) {
372   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
373   Status error;
374 
375   if (log)
376     log->Printf("PlatformRemoteGDBServer::%s() called", __FUNCTION__);
377 
378   auto num_file_actions = launch_info.GetNumFileActions();
379   for (decltype(num_file_actions) i = 0; i < num_file_actions; ++i) {
380     const auto file_action = launch_info.GetFileActionAtIndex(i);
381     if (file_action->GetAction() != FileAction::eFileActionOpen)
382       continue;
383     switch (file_action->GetFD()) {
384     case STDIN_FILENO:
385       m_gdb_client.SetSTDIN(file_action->GetFileSpec());
386       break;
387     case STDOUT_FILENO:
388       m_gdb_client.SetSTDOUT(file_action->GetFileSpec());
389       break;
390     case STDERR_FILENO:
391       m_gdb_client.SetSTDERR(file_action->GetFileSpec());
392       break;
393     }
394   }
395 
396   m_gdb_client.SetDisableASLR(
397       launch_info.GetFlags().Test(eLaunchFlagDisableASLR));
398   m_gdb_client.SetDetachOnError(
399       launch_info.GetFlags().Test(eLaunchFlagDetachOnError));
400 
401   FileSpec working_dir = launch_info.GetWorkingDirectory();
402   if (working_dir) {
403     m_gdb_client.SetWorkingDir(working_dir);
404   }
405 
406   // Send the environment and the program + arguments after we connect
407   m_gdb_client.SendEnvironment(launch_info.GetEnvironment());
408 
409   ArchSpec arch_spec = launch_info.GetArchitecture();
410   const char *arch_triple = arch_spec.GetTriple().str().c_str();
411 
412   m_gdb_client.SendLaunchArchPacket(arch_triple);
413   if (log)
414     log->Printf(
415         "PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'",
416         __FUNCTION__, arch_triple ? arch_triple : "<NULL>");
417 
418   int arg_packet_err;
419   {
420     // Scope for the scoped timeout object
421     process_gdb_remote::GDBRemoteCommunication::ScopedTimeout timeout(
422         m_gdb_client, std::chrono::seconds(5));
423     arg_packet_err = m_gdb_client.SendArgumentsPacket(launch_info);
424   }
425 
426   if (arg_packet_err == 0) {
427     std::string error_str;
428     if (m_gdb_client.GetLaunchSuccess(error_str)) {
429       const auto pid = m_gdb_client.GetCurrentProcessID(false);
430       if (pid != LLDB_INVALID_PROCESS_ID) {
431         launch_info.SetProcessID(pid);
432         if (log)
433           log->Printf("PlatformRemoteGDBServer::%s() pid %" PRIu64
434                       " launched successfully",
435                       __FUNCTION__, pid);
436       } else {
437         if (log)
438           log->Printf("PlatformRemoteGDBServer::%s() launch succeeded but we "
439                       "didn't get a valid process id back!",
440                       __FUNCTION__);
441         error.SetErrorString("failed to get PID");
442       }
443     } else {
444       error.SetErrorString(error_str.c_str());
445       if (log)
446         log->Printf("PlatformRemoteGDBServer::%s() launch failed: %s",
447                     __FUNCTION__, error.AsCString());
448     }
449   } else {
450     error.SetErrorStringWithFormat("'A' packet returned an error: %i",
451                                    arg_packet_err);
452   }
453   return error;
454 }
455 
456 Status PlatformRemoteGDBServer::KillProcess(const lldb::pid_t pid) {
457   if (!KillSpawnedProcess(pid))
458     return Status("failed to kill remote spawned process");
459   return Status();
460 }
461 
462 lldb::ProcessSP PlatformRemoteGDBServer::DebugProcess(
463     ProcessLaunchInfo &launch_info, Debugger &debugger,
464     Target *target, // Can be NULL, if NULL create a new target, else use
465                     // existing one
466     Status &error) {
467   lldb::ProcessSP process_sp;
468   if (IsRemote()) {
469     if (IsConnected()) {
470       lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
471       std::string connect_url;
472       if (!LaunchGDBServer(debugserver_pid, connect_url)) {
473         error.SetErrorStringWithFormat("unable to launch a GDB server on '%s'",
474                                        GetHostname());
475       } else {
476         if (target == NULL) {
477           TargetSP new_target_sp;
478 
479           error = debugger.GetTargetList().CreateTarget(
480               debugger, "", "", eLoadDependentsNo, NULL, new_target_sp);
481           target = new_target_sp.get();
482         } else
483           error.Clear();
484 
485         if (target && error.Success()) {
486           debugger.GetTargetList().SetSelectedTarget(target);
487 
488           // The darwin always currently uses the GDB remote debugger plug-in
489           // so even when debugging locally we are debugging remotely!
490           process_sp = target->CreateProcess(launch_info.GetListener(),
491                                              "gdb-remote", NULL);
492 
493           if (process_sp) {
494             error = process_sp->ConnectRemote(nullptr, connect_url.c_str());
495             // Retry the connect remote one time...
496             if (error.Fail())
497               error = process_sp->ConnectRemote(nullptr, connect_url.c_str());
498             if (error.Success())
499               error = process_sp->Launch(launch_info);
500             else if (debugserver_pid != LLDB_INVALID_PROCESS_ID) {
501               printf("error: connect remote failed (%s)\n", error.AsCString());
502               KillSpawnedProcess(debugserver_pid);
503             }
504           }
505         }
506       }
507     } else {
508       error.SetErrorString("not connected to remote gdb server");
509     }
510   }
511   return process_sp;
512 }
513 
514 bool PlatformRemoteGDBServer::LaunchGDBServer(lldb::pid_t &pid,
515                                               std::string &connect_url) {
516   ArchSpec remote_arch = GetRemoteSystemArchitecture();
517   llvm::Triple &remote_triple = remote_arch.GetTriple();
518 
519   uint16_t port = 0;
520   std::string socket_name;
521   bool launch_result = false;
522   if (remote_triple.getVendor() == llvm::Triple::Apple &&
523       remote_triple.getOS() == llvm::Triple::IOS) {
524     // When remote debugging to iOS, we use a USB mux that always talks to
525     // localhost, so we will need the remote debugserver to accept connections
526     // only from localhost, no matter what our current hostname is
527     launch_result =
528         m_gdb_client.LaunchGDBServer("127.0.0.1", pid, port, socket_name);
529   } else {
530     // All other hosts should use their actual hostname
531     launch_result =
532         m_gdb_client.LaunchGDBServer(nullptr, pid, port, socket_name);
533   }
534 
535   if (!launch_result)
536     return false;
537 
538   connect_url =
539       MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, port,
540                        (socket_name.empty()) ? nullptr : socket_name.c_str());
541   return true;
542 }
543 
544 bool PlatformRemoteGDBServer::KillSpawnedProcess(lldb::pid_t pid) {
545   return m_gdb_client.KillSpawnedProcess(pid);
546 }
547 
548 lldb::ProcessSP PlatformRemoteGDBServer::Attach(
549     ProcessAttachInfo &attach_info, Debugger &debugger,
550     Target *target, // Can be NULL, if NULL create a new target, else use
551                     // existing one
552     Status &error) {
553   lldb::ProcessSP process_sp;
554   if (IsRemote()) {
555     if (IsConnected()) {
556       lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
557       std::string connect_url;
558       if (!LaunchGDBServer(debugserver_pid, connect_url)) {
559         error.SetErrorStringWithFormat("unable to launch a GDB server on '%s'",
560                                        GetHostname());
561       } else {
562         if (target == NULL) {
563           TargetSP new_target_sp;
564 
565           error = debugger.GetTargetList().CreateTarget(
566               debugger, "", "", eLoadDependentsNo, NULL, new_target_sp);
567           target = new_target_sp.get();
568         } else
569           error.Clear();
570 
571         if (target && error.Success()) {
572           debugger.GetTargetList().SetSelectedTarget(target);
573 
574           // The darwin always currently uses the GDB remote debugger plug-in
575           // so even when debugging locally we are debugging remotely!
576           process_sp = target->CreateProcess(
577               attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
578           if (process_sp) {
579             error = process_sp->ConnectRemote(nullptr, connect_url.c_str());
580             if (error.Success()) {
581               ListenerSP listener_sp = attach_info.GetHijackListener();
582               if (listener_sp)
583                 process_sp->HijackProcessEvents(listener_sp);
584               error = process_sp->Attach(attach_info);
585             }
586 
587             if (error.Fail() && debugserver_pid != LLDB_INVALID_PROCESS_ID) {
588               KillSpawnedProcess(debugserver_pid);
589             }
590           }
591         }
592       }
593     } else {
594       error.SetErrorString("not connected to remote gdb server");
595     }
596   }
597   return process_sp;
598 }
599 
600 Status PlatformRemoteGDBServer::MakeDirectory(const FileSpec &file_spec,
601                                               uint32_t mode) {
602   Status error = m_gdb_client.MakeDirectory(file_spec, mode);
603   Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
604   if (log)
605     log->Printf("PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) "
606                 "error = %u (%s)",
607                 file_spec.GetCString(), mode, error.GetError(),
608                 error.AsCString());
609   return error;
610 }
611 
612 Status PlatformRemoteGDBServer::GetFilePermissions(const FileSpec &file_spec,
613                                                    uint32_t &file_permissions) {
614   Status error = m_gdb_client.GetFilePermissions(file_spec, file_permissions);
615   Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
616   if (log)
617     log->Printf("PlatformRemoteGDBServer::GetFilePermissions(path='%s', "
618                 "file_permissions=%o) error = %u (%s)",
619                 file_spec.GetCString(), file_permissions, error.GetError(),
620                 error.AsCString());
621   return error;
622 }
623 
624 Status PlatformRemoteGDBServer::SetFilePermissions(const FileSpec &file_spec,
625                                                    uint32_t file_permissions) {
626   Status error = m_gdb_client.SetFilePermissions(file_spec, file_permissions);
627   Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
628   if (log)
629     log->Printf("PlatformRemoteGDBServer::SetFilePermissions(path='%s', "
630                 "file_permissions=%o) error = %u (%s)",
631                 file_spec.GetCString(), file_permissions, error.GetError(),
632                 error.AsCString());
633   return error;
634 }
635 
636 lldb::user_id_t PlatformRemoteGDBServer::OpenFile(const FileSpec &file_spec,
637                                                   uint32_t flags, uint32_t mode,
638                                                   Status &error) {
639   return m_gdb_client.OpenFile(file_spec, flags, mode, error);
640 }
641 
642 bool PlatformRemoteGDBServer::CloseFile(lldb::user_id_t fd, Status &error) {
643   return m_gdb_client.CloseFile(fd, error);
644 }
645 
646 lldb::user_id_t
647 PlatformRemoteGDBServer::GetFileSize(const FileSpec &file_spec) {
648   return m_gdb_client.GetFileSize(file_spec);
649 }
650 
651 uint64_t PlatformRemoteGDBServer::ReadFile(lldb::user_id_t fd, uint64_t offset,
652                                            void *dst, uint64_t dst_len,
653                                            Status &error) {
654   return m_gdb_client.ReadFile(fd, offset, dst, dst_len, error);
655 }
656 
657 uint64_t PlatformRemoteGDBServer::WriteFile(lldb::user_id_t fd, uint64_t offset,
658                                             const void *src, uint64_t src_len,
659                                             Status &error) {
660   return m_gdb_client.WriteFile(fd, offset, src, src_len, error);
661 }
662 
663 Status PlatformRemoteGDBServer::PutFile(const FileSpec &source,
664                                         const FileSpec &destination,
665                                         uint32_t uid, uint32_t gid) {
666   return Platform::PutFile(source, destination, uid, gid);
667 }
668 
669 Status PlatformRemoteGDBServer::CreateSymlink(
670     const FileSpec &src, // The name of the link is in src
671     const FileSpec &dst) // The symlink points to dst
672 {
673   Status error = m_gdb_client.CreateSymlink(src, dst);
674   Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
675   if (log)
676     log->Printf("PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') "
677                 "error = %u (%s)",
678                 src.GetCString(), dst.GetCString(), error.GetError(),
679                 error.AsCString());
680   return error;
681 }
682 
683 Status PlatformRemoteGDBServer::Unlink(const FileSpec &file_spec) {
684   Status error = m_gdb_client.Unlink(file_spec);
685   Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
686   if (log)
687     log->Printf("PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)",
688                 file_spec.GetCString(), error.GetError(), error.AsCString());
689   return error;
690 }
691 
692 bool PlatformRemoteGDBServer::GetFileExists(const FileSpec &file_spec) {
693   return m_gdb_client.GetFileExists(file_spec);
694 }
695 
696 Status PlatformRemoteGDBServer::RunShellCommand(
697     const char *command, // Shouldn't be NULL
698     const FileSpec &
699         working_dir, // Pass empty FileSpec to use the current working directory
700     int *status_ptr, // Pass NULL if you don't want the process exit status
701     int *signo_ptr,  // Pass NULL if you don't want the signal that caused the
702                      // process to exit
703     std::string
704         *command_output, // Pass NULL if you don't want the command output
705     const Timeout<std::micro> &timeout) {
706   return m_gdb_client.RunShellCommand(command, working_dir, status_ptr,
707                                       signo_ptr, command_output, timeout);
708 }
709 
710 void PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames() {
711   m_trap_handlers.push_back(ConstString("_sigtramp"));
712 }
713 
714 const UnixSignalsSP &PlatformRemoteGDBServer::GetRemoteUnixSignals() {
715   if (!IsConnected())
716     return Platform::GetRemoteUnixSignals();
717 
718   if (m_remote_signals_sp)
719     return m_remote_signals_sp;
720 
721   // If packet not implemented or JSON failed to parse, we'll guess the signal
722   // set based on the remote architecture.
723   m_remote_signals_sp = UnixSignals::Create(GetRemoteSystemArchitecture());
724 
725   StringExtractorGDBRemote response;
726   auto result = m_gdb_client.SendPacketAndWaitForResponse("jSignalsInfo",
727                                                           response, false);
728 
729   if (result != decltype(result)::Success ||
730       response.GetResponseType() != response.eResponse)
731     return m_remote_signals_sp;
732 
733   auto object_sp = StructuredData::ParseJSON(response.GetStringRef());
734   if (!object_sp || !object_sp->IsValid())
735     return m_remote_signals_sp;
736 
737   auto array_sp = object_sp->GetAsArray();
738   if (!array_sp || !array_sp->IsValid())
739     return m_remote_signals_sp;
740 
741   auto remote_signals_sp = std::make_shared<lldb_private::GDBRemoteSignals>();
742 
743   bool done = array_sp->ForEach(
744       [&remote_signals_sp](StructuredData::Object *object) -> bool {
745         if (!object || !object->IsValid())
746           return false;
747 
748         auto dict = object->GetAsDictionary();
749         if (!dict || !dict->IsValid())
750           return false;
751 
752         // Signal number and signal name are required.
753         int signo;
754         if (!dict->GetValueForKeyAsInteger("signo", signo))
755           return false;
756 
757         llvm::StringRef name;
758         if (!dict->GetValueForKeyAsString("name", name))
759           return false;
760 
761         // We can live without short_name, description, etc.
762         bool suppress{false};
763         auto object_sp = dict->GetValueForKey("suppress");
764         if (object_sp && object_sp->IsValid())
765           suppress = object_sp->GetBooleanValue();
766 
767         bool stop{false};
768         object_sp = dict->GetValueForKey("stop");
769         if (object_sp && object_sp->IsValid())
770           stop = object_sp->GetBooleanValue();
771 
772         bool notify{false};
773         object_sp = dict->GetValueForKey("notify");
774         if (object_sp && object_sp->IsValid())
775           notify = object_sp->GetBooleanValue();
776 
777         std::string description{""};
778         object_sp = dict->GetValueForKey("description");
779         if (object_sp && object_sp->IsValid())
780           description = object_sp->GetStringValue();
781 
782         remote_signals_sp->AddSignal(signo, name.str().c_str(), suppress, stop,
783                                      notify, description.c_str());
784         return true;
785       });
786 
787   if (done)
788     m_remote_signals_sp = std::move(remote_signals_sp);
789 
790   return m_remote_signals_sp;
791 }
792 
793 std::string PlatformRemoteGDBServer::MakeGdbServerUrl(
794     const std::string &platform_scheme, const std::string &platform_hostname,
795     uint16_t port, const char *socket_name) {
796   const char *override_scheme =
797       getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME");
798   const char *override_hostname =
799       getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME");
800   const char *port_offset_c_str =
801       getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET");
802   int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0;
803 
804   return MakeUrl(override_scheme ? override_scheme : platform_scheme.c_str(),
805                  override_hostname ? override_hostname
806                                    : platform_hostname.c_str(),
807                  port + port_offset, socket_name);
808 }
809 
810 std::string PlatformRemoteGDBServer::MakeUrl(const char *scheme,
811                                              const char *hostname,
812                                              uint16_t port, const char *path) {
813   StreamString result;
814   result.Printf("%s://%s", scheme, hostname);
815   if (port != 0)
816     result.Printf(":%u", port);
817   if (path)
818     result.Write(path, strlen(path));
819   return result.GetString();
820 }
821 
822 lldb::ProcessSP PlatformRemoteGDBServer::ConnectProcess(
823     llvm::StringRef connect_url, llvm::StringRef plugin_name,
824     lldb_private::Debugger &debugger, lldb_private::Target *target,
825     lldb_private::Status &error) {
826   if (!IsRemote() || !IsConnected()) {
827     error.SetErrorString("Not connected to remote gdb server");
828     return nullptr;
829   }
830   return Platform::ConnectProcess(connect_url, plugin_name, debugger, target,
831                                   error);
832 }
833 
834 size_t PlatformRemoteGDBServer::ConnectToWaitingProcesses(Debugger &debugger,
835                                                           Status &error) {
836   std::vector<std::string> connection_urls;
837   GetPendingGdbServerList(connection_urls);
838 
839   for (size_t i = 0; i < connection_urls.size(); ++i) {
840     ConnectProcess(connection_urls[i].c_str(), "", debugger, nullptr, error);
841     if (error.Fail())
842       return i; // We already connected to i process succsessfully
843   }
844   return connection_urls.size();
845 }
846 
847 size_t PlatformRemoteGDBServer::GetPendingGdbServerList(
848     std::vector<std::string> &connection_urls) {
849   std::vector<std::pair<uint16_t, std::string>> remote_servers;
850   m_gdb_client.QueryGDBServer(remote_servers);
851   for (const auto &gdbserver : remote_servers) {
852     const char *socket_name_cstr =
853         gdbserver.second.empty() ? nullptr : gdbserver.second.c_str();
854     connection_urls.emplace_back(
855         MakeGdbServerUrl(m_platform_scheme, m_platform_hostname,
856                          gdbserver.first, socket_name_cstr));
857   }
858   return connection_urls.size();
859 }
860